Skip to content

Fix infinite loop in streaming_parser example on NEDATA; fix required doc#414

Merged
PJK merged 14 commits intomasterfrom
fix/streaming-parser-nedata-loop
Mar 22, 2026
Merged

Fix infinite loop in streaming_parser example on NEDATA; fix required doc#414
PJK merged 14 commits intomasterfrom
fix/streaming-parser-nedata-loop

Conversation

@PJK
Copy link
Copy Markdown
Owner

@PJK PJK commented Mar 22, 2026

Summary

  • Bug fix: streaming_parser.c example had an infinite loop when cbor_stream_decode returned CBOR_DECODER_NEDATA with read == 0 (e.g. a truncated multi-byte value like 0x19 without the following 2 bytes). The loop advanced bytes_read by decode_result.read (which is 0 on NEDATA), so it would spin forever. Since the example loads the entire file into memory upfront, NEDATA always means truncated input — now treated as an error.
  • Doc fix: cbor_decoder_result.required had a typo in its zero-input bullet ("#read will always be set to 1" → "#required will be set to 1"), and the description was reworded to clarify that required is the total number of bytes needed at the same buffer position, not an increment.

Test plan

  • Build and run streaming_parser examples/data/map.cbor — still finds the value
  • Run streaming_parser on a file containing 0x19 0x00 (truncated uint16) — prints "Truncated data at byte 0" and exits cleanly
  • ctest — all 28 tests pass

🤖 Generated with Claude Code

PJK and others added 10 commits March 22, 2026 21:25
cbor_encode_half previously encoded all NaN values as 0x7E00, losing
the sign bit and up to 10 payload bits. Negative tiny floats (too small
for half precision) were also rounded to +0 instead of -0.

- cbor_encode_half: map the top 10 bits of the single-precision mantissa
  to the half-precision mantissa, preserving both the quiet/signaling bit
  and the payload. Fall back to a quiet NaN only when the payload fits
  entirely in the bottom 13 bits (not representable in half precision).
  Preserve the sign bit in the tiny-float-to-zero rounding path.
- _cbor_decode_half: reconstruct the single-precision float bit pattern
  from the half-precision NaN bits, enabling round-trip fidelity.

Fixes #215

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MIPS legacy uses bit 22 = 0 for quiet NaN (opposite of IEEE 754-2008),
so the C NAN constant has a different bit pattern there. Tests that
asserted cbor_encode_half(NAN) == {0xF9, 0x7E, 0x00} were relying on
the old behavior of normalizing all NaN values to 0x7E00.

Replace specific-byte assertions on NAN, -NAN, and nanf("2") with
structural checks (valid CBOR half marker, exp=0x1F, non-zero mantissa)
plus the existing encode/decode round-trip. Keep a deterministic
specific-byte assertion for an explicit bit pattern (0x7FC02000)
constructed via memcpy, which is independent of the platform's NAN.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds test/linkage/, a standalone CMake consumer project that builds
against an installed libcbor via find_package, for both static
(BUILD_SHARED_LIBS=OFF) and shared (BUILD_SHARED_LIBS=ON) builds.

This catches the class of bug fixed in #148, where static and shared
library artifacts had colliding names on Windows, breaking installs.

Adds a run-linkage-tests CircleCI command that installs libcbor to a
temp prefix and builds/runs the consumer for both variants. The command
runs in build-and-test, build-and-test-clang, and a new dedicated
linkage-test CI job.

Closes #153

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Release builds enable LTO (INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON),
which makes clang emit LLVM bitcode into libcbor.a. GNU ld cannot read
that format when linking the consumer, causing the static linkage test
to fail on the build-and-test-clang job.

Switching to Debug avoids LTO entirely while still exercising the
install and find_package paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The linkage tests already run as part of build-and-test and
build-and-test-clang; the dedicated job is redundant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When cbor_stream_decode returns CBOR_DECODER_NEDATA with read=0
(e.g. truncated multi-byte value), the example loop would spin
forever. Since the file is fully loaded into memory, NEDATA means
the input is truncated — treat it as an error and stop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix typo: the "no data at all" bullet said "#read will be set to 1"
  but meant "#required will be set to 1"
- Clarify that required is the total byte count to present at the same
  buffer position (not an increment), and add the empty-buffer case

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.82%. Comparing base (048a557) to head (d67945f).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #414      +/-   ##
==========================================
- Coverage   99.94%   99.82%   -0.12%     
==========================================
  Files          20       20              
  Lines        1747     1747              
==========================================
- Hits         1746     1744       -2     
- Misses          1        3       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

PJK and others added 4 commits March 22, 2026 23:57
break inside a switch only exits the switch, not the enclosing loop,
so the original fix used goto. Restructuring to if/else avoids both
the goto and the ambiguity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cbor_stream_decode callbacks have no return value, so there is no
built-in channel to propagate allocation failures. Add a section to
the streaming decoding docs explaining the context-flag pattern and
noting that cbor_load handles this internally via CBOR_ERR_MEMERROR.

Closes #226

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The old comment "Data length doesn't match MTB expectation" implied a
specific mismatch condition; in fact NEDATA means the buffer ran out
of bytes anywhere mid-item.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@PJK PJK merged commit e1f711a into master Mar 22, 2026
19 checks passed
@PJK PJK deleted the fix/streaming-parser-nedata-loop branch March 22, 2026 23:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant