Repair a native parser using an actual sanitizer report
Requires Clang with AddressSanitizer/UndefinedBehaviorSanitizer and Python 3.11+.
Verified with Apple Clang 21 on macOS. Linux Clang is supported when its sanitizer
runtime is installed. Set CC to an alternative compatible Clang executable.

Reference solution: not included here, so the exercise does not hand you the answer.
Attempt the repair first. Then download native-memory-safety-solution.zip from the project card
on https://softwaresecurity.com/labs/#project-native-memory-safety and extract it into this folder;
it adds reference.c without changing your files, and the reference commands below
need it.

Objective: distinguish the input allocation, the wire-declared length and the
output capacity. Establish all three bounds before touching payload bytes.
Prerequisites: C pointers, arrays, size_t, byte order and compiler diagnostics.

Wire contract
Two big-endian bytes declare a payload of 1..64 bytes. Payload characters must
be ASCII A-Z, a-z, 0-9, underscore or hyphen. No NULs, spaces or trailing bytes.
The destination buffer has 65 bytes so a valid 64-byte name gets a terminator.

1. Run python3 reproduce.py. It builds the intentionally broken starter with
   -fsanitize=address,undefined, supplies a three-byte file and prints an actual
   AddressSanitizer report. Mark the allocation size, attempted read size and
   call stack. Input 00 08 41 claims eight payload bytes but contains only one.
   There is no service, exploit payload or real target; files/binaries are
   generated in a temporary directory and removed when the command completes.
2. Run python3 test_parser.py. Some legitimate cases pass; invalid frames must
   return REJECT (exit 2), not crash. Tool/setup errors are not expected failures.
3. Repair parse_name in exercise.c. Before reading the length, check size >= 2.
   Reject lengths outside 1..64. Then compare size - 2 to length, after proving
   subtraction is safe. Equality also rejects trailing data. Explain why merely
   checking output capacity would still allow the truncated-payload read.
4. Validate each payload byte using explicit ASCII ranges before copying. Then
   copy exactly length bytes and write the terminator inside the destination.
   Do not use strlen on untrusted wire data, strip forbidden bytes, disable
   sanitizer flags or enlarge output until the failing cases happen to fit.
5. Run python3 test_parser.py until all 11 tests pass. The last test generates 80
   reproducible valid/malformed frames. A sanitizer-clean run alone is not
   enough: ordinary schema errors must also be rejected, and valid names must
   still round-trip exactly. Compare reference.c after attempting your repair.
   Reference: EXERCISE_MODULE=reference python3 test_parser.py
   PowerShell: $env:EXERCISE_MODULE='reference'; python test_parser.py
   Remove the variable before checking your changes.

Keep: annotated sanitizer report; a three-column bounds table (allocation,
declared length, output capacity); the passing test output and one new malformed
frame with its expected result. Complete when both sanitizer and contract checks
pass, including length 64, length 65, truncation, NUL and trailing-byte cases.

Scope: actual compiled C and instrumented memory access; a deliberately small
file parser with a 4 KiB harness input cap. It does not establish safety of an
entire program. AddressSanitizer detects exercised memory faults, not all logic
errors; expand corpus/fuzzing and prefer memory-safe languages where feasible.
The driver creates an exact-size heap input so the truncated read is observable.
Leak checking is disabled for portability; address/undefined checks remain on.
Parser callers must honor out's documented 65-byte capacity and pointer validity.

Sources (checked 9 October 2026):
https://clang.llvm.org/docs/AddressSanitizer.html
https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
https://cwe.mitre.org/data/definitions/125.html
https://cwe.mitre.org/data/definitions/787.html

Dev container
.devcontainer/devcontainer.json opens this folder in VS Code Dev Containers or
GitHub Codespaces using the Dev Containers C++ image (Clang with
AddressSanitizer and UndefinedBehaviorSanitizer, and Python 3), pinned by
digest. Run the commands above in its terminal.
