Repository navigation
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #5125 +/- ##
==========================================
+ Coverage 80.07% 80.78% +0.70%
==========================================
Files 375 375
Lines 98740 99974 +1234
==========================================
+ Hits 79065 80760 +1695
+ Misses 19675 19214 -461
🚀 New features to boost your workflow:
|
5f9b34d to
414ac55
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
It makes wide-reaching changes across CBOR core encoding/decoding and packet cache semantics, which warrants careful human validation beyond static review.
Pull request overview
This PR refactors Scapy’s CBOR support toward Scapy-native field conventions (Python-native values, ASN.1-like hooks), strengthens codec correctness (maps, floats, optionals, nesting/indefinite handling, deterministic encoding), and adds an isolated cbor2-based interoperability/differential test lane in tox and CI.
Changes:
- Rework CBOR field/container APIs to use Scapy-style
any2i/i2m/m2iplusbuild_result/dissect_result, with improved raw-cache fidelity and parent/child ownership handling. - Harden CBOR codec behavior (indefinite containers, duplicate keys, preferred float widths, deterministic map ordering, max nesting) and introduce CBOR map pair preservation (
CBORMapData). - Add pinned
cbor2==6.1.4differential UTScapy campaign plus a dedicated tox env and GitHub Actions job.
File summaries
| File | Description |
|---|---|
tox.ini |
Adds a dedicated cbor2 tox env for pinned differential tests; removes cbor2 from main deps. |
test/scapy/layers/requirements-cbor2.txt |
Documents/pins optional cbor2 dependency for interop testing. |
test/scapy/layers/generate_cbor2_corpus.py |
Adds helper script to generate reproducible CBOR corpora using cbor2. |
test/scapy/layers/cbor_cbor2_interop.uts |
Adds extensive cbor2-vs-Scapy differential/interoperability coverage. |
test/fields.uts |
Adds a regression test around ConditionalField.__getattr__. |
test/configs/windows2.utsc |
Excludes the cbor2 interop campaign from default Windows2 runs and marks keyword. |
test/configs/windows.utsc |
Excludes the cbor2 interop campaign from default Windows runs and marks keyword. |
test/configs/solaris.utsc |
Excludes the cbor2 interop campaign from default Solaris runs and marks keyword. |
test/configs/linux.utsc |
Excludes the cbor2 interop campaign from default Linux runs and marks keyword. |
test/configs/bsd.utsc |
Excludes the cbor2 interop campaign from default BSD runs and marks keyword. |
scapy/cborpacket.py |
Adds CBOR-specific packet cache integration, default-copy deepening, and parent reattachment on copy. |
scapy/cbor/cborfields.py |
Major CBOR field API rewrite (native values, optional/conditional semantics, sequences, deterministic map schema behavior). |
scapy/cbor/cborcodec.py |
Hardens low-level codec: nesting limit, indefinite support, strictness checks, float width preference, deterministic encoding helpers. |
scapy/cbor/cbor.py |
Introduces CBORMapData, richer equality/hash semantics, float encoding retention, and native wrapper classes. |
scapy/cbor/__init__.py |
Exposes new CBOR types/fields/results in the public API surface. |
README.md |
Fixes packaging status badge markdown formatting. |
.github/workflows/unittests.yml |
Adds a CI job running tox -e cbor2 on Python 3.12. |
Review details
- Files reviewed: 17/18 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Capture map-key equivalence, deterministic floats, hash/tag field semantics, and multi-map unknown ownership before changing the implementation. Co-authored-by: Cursor <cursoragent@cursor.com>
414ac55 to
4a552ff
Compare
Capture map-key equivalence, deterministic floats, hash/tag field semantics, and multi-map unknown ownership before changing the implementation. Co-authored-by: Cursor <cursoragent@cursor.com> AI-Assisted: yes (Composer)
4a552ff to
f9e6104
Compare
Capture map-key equivalence, deterministic floats, hash/tag field semantics, and multi-map unknown ownership before changing the implementation. Co-authored-by: Cursor <cursoragent@cursor.com> AI-Assisted: yes (Composer)
b433d7e to
06a065b
Compare
|
@gpotter2 I've done with a lot of refactorings and a manual review; Could you please have a look? |
Capture map-key equivalence, deterministic floats, hash/tag field semantics, and multi-map unknown ownership before changing the implementation. Co-authored-by: Cursor <cursoragent@cursor.com> AI-Assisted: yes (Composer)
b7fc549 to
1f059ae
Compare
Capture map-key equivalence, deterministic floats, hash/tag field semantics, and multi-map unknown ownership before changing the implementation. Co-authored-by: Cursor <cursoragent@cursor.com> AI-Assisted: yes (Composer)
1f059ae to
fce7bb4
Compare
|
@gpotter2 Could you please have a look? |
Capture map-key equivalence, deterministic floats, hash/tag field semantics, and multi-map unknown ownership before changing the implementation. Co-authored-by: Cursor <cursoragent@cursor.com> AI-Assisted: yes (Composer)
fce7bb4 to
f16842e
Compare
|
I was looking at the CBOR doc yesterday, I don't find it particularly useful teaching how to actually make CBOR packets. Could you drop anything's that been written unsupervised by AI? Thx Do you want me to take a look at this PR again? |
|
I'll rework the docs. Could you please have a look on the code. |
|
@gpotter2 I've rewritten the docs file and reviewed it. |
Count preserved unknown MAP members in is_empty, encode nested ARRAY_OF fields, and reject remainder/kwargs misplacements. AI-Assisted: yes (Cursor Grok 4.6) Co-authored-by: Cursor <cursoragent@cursor.com>
Cover CBORF_ITEMS TypeError for unexpected keywords alongside the existing ARRAY encode_indefinite case. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Stop conditional suffix reservation from using undecoded discriminators, initialize zero-budget remainders and nested optionals, fingerprint float bit patterns, and reject nested packet-valued homogeneous collections. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Inline unframed ITEMS into array schemas for budgeting, reserve conditionals only after required predecessors are decoded, and trim preferred-float helpers. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the positional between-required heuristic with reservation based on already-decoded field names so unrelated required fields do not suppress a known active conditional. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Put external_cbor2 on the interop campaign, assert preferred float wire bytes, fix indefinite budget and ITEMS payload checks, and drop the non-determinism scanner helper. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Proxy getfieldval and subclass methods on the reservation view, propagate real predicate errors, cap indefinite min_items work instead of requiring quadratic growth, and trim interop helpers. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the fake reservation view. Predicates run on the packet; unread fields do not reserve from defaults. Map dissection uses field wrappers, and UTS covers greedy optional-before-flag. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Drop unread-field interception. Suffix reservation uses min_items on the real packet. Default-on trailing conditionals over-reserve until the discriminator is dissected. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Only optionals inspect the suffix. Conditionals reserve when named discriminators are already in pkt.fields, so default-on flags round-trip instead of rejecting their own encodings. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Unread default-on conditionals no longer starve a preceding optional during suffix budgeting. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
A skipped conditional is decided but never stored in pkt.fields, so later depends_on treated it as unread. AI-Assisted: yes (Cursor Grok 4.6) Co-authored-by: Cursor <cursoragent@cursor.com>
depends_on does not delay ConditionalField evaluation. Unknown names include the conditional field in the error. AI-Assisted: yes (Cursor Grok 4.6) Co-authored-by: Cursor <cursoragent@cursor.com>
AI-Assisted: yes (Cursor Grok 4.6) Co-authored-by: Cursor <cursoragent@cursor.com>
AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Same-semantic child assignment clears the child cache; the parent must see that and rebuild overlong encodings. AI-Assisted: yes (Composer) Co-authored-by: Cursor <cursoragent@cursor.com>
Move the seeded corpus into the UTS campaign and remove the standalone generator and duplicate requirements file. AI-Assisted: yes (OpenCode, GPT-6.1)
Document native fields, optional values, and map handling. AI-Assisted: yes (OpenAI GPT-6.1-sol)
Keep null and undefined as explicit CBOR objects in packet fields. AI-Assisted: yes (OpenAI Codex)
Remove recursive cache fingerprints and normalize packet encodings on rebuild. AI-Assisted: yes (OpenAI Codex)
Keep internal item accounting while honoring build, dissect, and m2i overrides on compound fields. AI-Assisted: yes (OpenAI Codex)
Rename the collection base and keep array reservation logic beside child dissection. AI-Assisted: yes (OpenAI Codex)
Keep payload-sensitive width selection in enc_float and simplify deterministic value dispatch. AI-Assisted: yes (OpenAI Codex)
Remove the header sentinel and counted-hook introduction, and keep buffer scans and imports consistent. AI-Assisted: yes (OpenAI Codex)
Describe None as absence, explicit null and undefined objects, and normalization of decoded packets. AI-Assisted: yes (OpenAI Codex)
97d386c to
9761613
Compare
| value | ||
| ) | ||
| encoded_pairs.append((key_bytes, value_bytes)) | ||
| encoded_pairs.sort(key=lambda item: item[0]) |
| bsd-non_root: {envpython} {env:DISABLE_COVERAGE:-m coverage run} -m scapy.tools.UTscapy -c test/configs/bsd.utsc -K tshark -N {posargs} | ||
| bsd-root: sudo -E {envpython} {env:DISABLE_COVERAGE:-m coverage run} -m scapy.tools.UTscapy -c test/configs/bsd.utsc -K tshark {posargs} | ||
| windows: {envpython} {env:DISABLE_COVERAGE:-m coverage run} -m scapy.tools.UTscapy -c test/configs/windows.utsc {posargs} | ||
| linux-non_root: {envpython} {env:DISABLE_COVERAGE:-m coverage run} -m scapy.tools.UTscapy -c ./test/configs/linux.utsc -N {env:CBOR2_TEST_FLAGS:} {posargs} |
| CBOR (Concise Binary Object Representation) is a binary data format defined | ||
| in `RFC 8949 <https://www.rfc-editor.org/rfc/rfc8949.html>`_. Scapy provides | ||
| CBOR objects and codecs for individual values, and ``CBOR_Packet`` with | ||
| ``CBORF_*`` fields for describing packet formats. No external CBOR library | ||
| is required. |



Summary
Stack
PR 2 of 3. Depends on #5124 (CRC presets). Reviewable CBOR-only commits sit on top of that foundation; next is BPv7 contrib.
Test plan
./test/run_tests -t test/scapy/layers/cbor.uts -Ntox -e cbor2(Python 3.12)