# Harden LYB parsing against truncated memory input#2538
Open
Alearner12 wants to merge 1 commit into
Open
Conversation
## Summary This change hardens the LYB data parser against arithmetic and bounds issues when parsing binary data from memory-backed inputs. - Adds length-aware memory input helpers so binary parsers can be given an explicit buffer size. - Rejects LYB parsing from legacy unbounded memory inputs, which are intended for NULL-terminated text data. - Checks all LYB reads and skips for end-of-input before copying or advancing the input cursor. - Propagates truncated-input failures through LYB count, size, string, value, hash, header, and node parsing paths. - Converts malformed schema-hash collision/prefix cases into validation errors instead of parser assertions. - Adds a dedicated LYB memory fuzz target that exercises the length-aware memory parsing path. ## Bug The LYB parser reads a binary format, but memory-backed inputs created with `ly_in_new_memory()` do not carry an explicit length. That API is suitable for NULL-terminated text formats, but LYB data can contain embedded NULL bytes and must be parsed using a bounded byte buffer. Before this change, `lyb_read()` called `ly_in_read()` and `ly_in_skip()` without propagating short-read failures. For unbounded memory inputs, the low-level input code had no buffer length to check, so truncated LYB data passed through public memory parsing APIs could make the parser read past the allocated input buffer. Affected paths included: - LYB header and context-hash reads. - Node type and flags reads. - Variable-length count and size decoding. - String and value payload reads. - Schema hash collision-chain decoding. Malformed inputs could also reach assertion-only schema hash checks, causing aborts instead of clean parser errors. ## Fix This PR makes LYB binary memory parsing explicit and fail-closed: - `struct ly_in` now records whether an input is bounded by `length`. - File and file-descriptor inputs are marked bounded because they are backed by mapped file lengths. - New `ly_in_new_memory_len()` API creates bounded memory inputs. - New `lyd_parse_data_mem_len()` wraps bounded memory parsing for callers that parse data directly from byte buffers. - `ly_in_read()`, `ly_in_peek()`, and `ly_in_skip()` check bounded inputs before reading or advancing. - `lyd_parse_lyb()` rejects `LY_IN_MEMORY` inputs that do not have an explicit length. - `lyb_read()`, `lyb_read_count()`, and `lyb_read_size()` now return `LY_ERR`, and their callers propagate errors. - Truncated LYB data now reports `Unexpected end of LYB data.` instead of reading past the input buffer. This keeps existing text-format memory parsing behavior intact while requiring LYB callers to use a length-aware memory input path. ## Files - `src/in_internal.h` - `src/in.h` - `src/in.c` - `src/parser_data.h` - `src/tree_data.c` - `src/parser_lyb.c` - `tests/fuzz/CMakeLists.txt` - `tests/fuzz/lyd_parse_mem_lyb.c` ## Tests Added fuzz coverage: - `lyd_parse_mem_lyb` Local verification performed: - Built libyang with ASan/UBSan enabled. - Confirmed a legacy unbounded memory LYB repro now fails closed with `LYB memory input requires an explicit input length.` - Confirmed bounded memory LYB parsing accepts a valid LYB sample. - Confirmed truncated bounded-memory LYB samples return parser errors without ASan reports. - Confirmed file-backed `yanglint` parsing of the same truncated LYB samples returns cleanly without sanitizer reports or assertion failures. Not run locally: ```bash ctest ``` CMocka was not available in my local environment, so the full upstream test suite should be run by CI or by a maintainer with the project test dependencies installed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Harden LYB parsing against truncated memory input
Summary
This change hardens the LYB data parser against arithmetic and bounds issues when parsing binary data from memory-backed inputs.
Bug
The LYB parser reads a binary format, but memory-backed inputs created with
ly_in_new_memory()do not carry an explicit length. That API is suitable for NULL-terminated text formats, but LYB data can contain embedded NULL bytes and must be parsed using a bounded byte buffer.Before this change,
lyb_read()calledly_in_read()andly_in_skip()without propagating short-read failures. For unbounded memory inputs, the low-level input code had no buffer length to check, so truncated LYB data passed through public memory parsing APIs could make the parser read past the allocated input buffer.Affected paths included:
Malformed inputs could also reach assertion-only schema hash checks, causing aborts instead of clean parser errors.
Fix
This PR makes LYB binary memory parsing explicit and fail-closed:
struct ly_innow records whether an input is bounded bylength.ly_in_new_memory_len()API creates bounded memory inputs.lyd_parse_data_mem_len()wraps bounded memory parsing for callers that parse data directly from byte buffers.ly_in_read(),ly_in_peek(), andly_in_skip()check bounded inputs before reading or advancing.lyd_parse_lyb()rejectsLY_IN_MEMORYinputs that do not have an explicit length.lyb_read(),lyb_read_count(), andlyb_read_size()now returnLY_ERR, and their callers propagate errors.Unexpected end of LYB data.instead of reading past the input buffer.This keeps existing text-format memory parsing behavior intact while requiring LYB callers to use a length-aware memory input path.
Tests
Added fuzz coverage:
lyd_parse_mem_lybLocal verification performed:
LYB memory input requires an explicit input length.yanglintparsing of the same truncated LYB samples returns cleanly without sanitizer reports or assertion failures.