From e70ac9d63e479486a92ed1cd73e6fa6a857d4eaa Mon Sep 17 00:00:00 2001 From: Roman Kharitonov Date: Thu, 12 Nov 2026 19:31:05 +1000 Subject: [PATCH] Update native Brotli and dr_libs Select the fixed Brotli 1.2.1 decoder through an official package-specific vcpkg registry and pin the used dr_libs headers to the qualified f12e197 snapshot. Advance the Godot patch version and bind license metadata to the new source bytes. Preserve historical scanner observations and explicitly label the three source-equivalent expectations derived from them. Cover qualified decoder selection and incomplete MP3 input with native regression checks. Keep the test decoder context on the heap within the existing stack-analysis limit. Co-Authored-By: Codex (gpt-6.1-sol) --- .ort/package-configurations/brotli.yml | 8 +- .ort/package-configurations/drlibs.yml | 12 +- ...build-tests-godot-minimal-registration.yml | 8 +- ...d-tests-license-package-configurations.yml | 24 ++-- build/license-inventory.json | 24 ++-- .../expected_artifacts.json | 15 +- .../firstparty_artifacts.json | 36 ++--- .../native_dependency_expectations.json | 101 ++++++++++++++ .../verified_header_snapshots.json | 40 ++++++ build/tests/native_dependency_expectations.py | 38 +++++ build/tests/test_dependency_updates.py | 18 +++ .../tests/test_godot_minimal_registration.py | 28 ++-- build/tests/test_godot_overlay_ports.py | 10 +- build/tests/test_license_inventory.py | 23 +++ .../test_license_package_configurations.py | 37 ++--- .../test_native_dependency_expectations.py | 132 ++++++++++++++++++ build/tests/test_real_header_bundles.py | 26 +++- build/vcpkg/ports/README.md | 19 ++- build/vcpkg/ports/drlibs/portfile.cmake | 12 +- build/vcpkg/ports/drlibs/vcpkg.json | 2 +- src/modules/godot/ChangeLog.en.txt | 4 + src/modules/godot/ChangeLog.ru.txt | 4 + src/modules/godot/VERSION | 2 +- src/tests/unit/audio_io.cpp | 13 ++ src/tests/unit/resource_compression.cpp | 8 +- vcpkg-configuration.json | 9 ++ vcpkg.json | 2 +- 27 files changed, 543 insertions(+), 112 deletions(-) create mode 100644 build/tests/fixtures/license_package_configurations/native_dependency_expectations.json create mode 100644 build/tests/fixtures/license_package_configurations/verified_header_snapshots.json create mode 100644 build/tests/native_dependency_expectations.py create mode 100644 build/tests/test_native_dependency_expectations.py diff --git a/.ort/package-configurations/brotli.yml b/.ort/package-configurations/brotli.yml index ae9a850..7282297 100644 --- a/.ort/package-configurations/brotli.yml +++ b/.ort/package-configurations/brotli.yml @@ -1,11 +1,11 @@ { - "id": "SpdxDocumentFile:vcpkg:brotli:1.2.0", - "source_artifact_url": "http://127.0.0.1:8765/sources/816c96e8e8f193b40151dad7e8ff37b1221d019dbcb9c35cd3fadbfe6477dfec.tar.gz", + "id": "SpdxDocumentFile:vcpkg:brotli:1.2.1", + "source_artifact_url": "http://127.0.0.1:8765/sources/98d35d11a78dc453aebb7d10c3748f3f73ff78c8267c0dc697b8631f67bf7e8f.tar.gz", "path_excludes": [ { - "pattern": "brotli-1.2.0/CONTRIBUTING.md", + "pattern": "brotli-1.2.1/CONTRIBUTING.md", "reason": "DOCUMENTATION_OF", - "comment": "Upstream contribution guide. Line 31 is the Google corporate CLA reference ([Software Grant and Corporate Contributor License Agreement]) that ScanCode reports as NOASSERTION; it is a non-code contribution document, not a grant of the library. The MIT source grants (the root LICENSE and every c/** header) stay detected unchanged. Anchored on the archive top directory brotli-1.2.0/ that the real ORT ScanCode run keeps in the extracted tree." + "comment": "Upstream contribution guide. Line 31 is the Google corporate CLA reference ([Software Grant and Corporate Contributor License Agreement]) that ScanCode reports as NOASSERTION; it is a non-code contribution document, not a grant of the library. The MIT source grants (the root LICENSE and every c/** header) stay detected unchanged. Anchored on the archive top directory brotli-1.2.1/ that the real ORT ScanCode run keeps in the extracted tree. CONTRIBUTING.md is byte-identical to1.2.0 in the verified1.2.1 source archive; this retains only the existing documentation scope." } ] } diff --git a/.ort/package-configurations/drlibs.yml b/.ort/package-configurations/drlibs.yml index 866b84b..98583b7 100644 --- a/.ort/package-configurations/drlibs.yml +++ b/.ort/package-configurations/drlibs.yml @@ -1,23 +1,23 @@ { - "id": "SpdxDocumentFile:vcpkg:drlibs:2026-08-31", - "source_artifact_url": "http://127.0.0.1:8765/sources/a57b4c054240bf7debd9fd58ecae8f47d55cae2addd0eee6c5a6569b3cec6f34.tar", + "id": "SpdxDocumentFile:vcpkg:drlibs:2026-11-11", + "source_artifact_url": "http://127.0.0.1:8765/sources/aa971fb36a7a147157e7726ec2311e1d46bd2d3cc80ce70efebdda9ce61e807a.tar", "license_finding_curations": [ { - "path": "dr_libs-dfe8377631000664666519fdb83da193fd8037f4-dr_mp3.h", + "path": "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_mp3.h", "start_lines": 2, "line_count": 1, "detected_license": "LicenseRef-scancode-unknown-license-reference", "reason": "CODE", - "comment": "Line 2 says the file is public domain and refers the reader to the license section at the end of the file; the footer (lines 5380-5422) offers Unlicense or MIT-0. The reference is not a separate license, and the real grants remain detected in the footer. The embedded lieff/minimp3 CC0 dedication at lines 5427-5429 is genuine provenance and is preserved.", + "comment": "Line 2 says the file is public domain and refers the reader to the license section at the end of the file; the footer (lines 5173-5215) offers Unlicense or MIT-0. The reference is not a separate license, and the real grants remain detected in the footer. The embedded lieff/minimp3 CC0 dedication at lines 5220-5222 is genuine provenance and is preserved. The scoped line2 text and complete grant footer are byte-identical to the prior reviewed snapshot; no new scanner observation is claimed.", "concluded_license": "NONE" }, { - "path": "dr_libs-dfe8377631000664666519fdb83da193fd8037f4-dr_wav.h", + "path": "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_wav.h", "start_lines": 2, "line_count": 1, "detected_license": "LicenseRef-scancode-unknown-license-reference", "reason": "CODE", - "comment": "Line 2 refers to the license section at the end of the file, whose footer (lines 9166-9208) offers Unlicense or MIT-0. The reference is not a separate license; the real grants stay detected.", + "comment": "Line 2 refers to the license section at the end of the file, whose footer (lines 8677-8719) offers Unlicense or MIT-0. The reference is not a separate license; the real grants stay detected. The scoped line2 text and complete grant footer are byte-identical to the prior reviewed snapshot; no new scanner observation is claimed.", "concluded_license": "NONE" } ] diff --git a/.ort/package-configurations/unpackrat-build-tests-godot-minimal-registration.yml b/.ort/package-configurations/unpackrat-build-tests-godot-minimal-registration.yml index 572fe92..66a5ebb 100644 --- a/.ort/package-configurations/unpackrat-build-tests-godot-minimal-registration.yml +++ b/.ort/package-configurations/unpackrat-build-tests-godot-minimal-registration.yml @@ -1,15 +1,15 @@ { - "id": "SpdxDocumentFile:vcpkg:unpackrat-build-tests-godot-minimal-registration:d213197f852ae31709506a4cbcfbbf9f86b051fd12061aa3c204642fc510aadc", - "source_artifact_url": "http://127.0.0.1:8765/sources/d213197f852ae31709506a4cbcfbbf9f86b051fd12061aa3c204642fc510aadc.tar", + "id": "SpdxDocumentFile:vcpkg:unpackrat-build-tests-godot-minimal-registration:6cf4db24494dd28bc7d3b323ed7e335851eb22fb9a88e29e1d98ade2c0d4bff3", + "source_artifact_url": "http://127.0.0.1:8765/sources/6cf4db24494dd28bc7d3b323ed7e335851eb22fb9a88e29e1d98ade2c0d4bff3.tar", "license_finding_curations": [ { "path": "build/tests/test_godot_minimal_registration.py", - "start_lines": "69,87,217", + "start_lines": "70,88,218", "line_count": 1, "detected_license": "GPL-3.0-only", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Lines 69,87,217 share the identifier GPL-3.0-only; line 69 is, for example, `\"GPL-3.0.txt\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." + "comment": "Lines 70,88,218 share the identifier GPL-3.0-only; line 70 is, for example, `\"GPL-3.0.txt\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." } ] } diff --git a/.ort/package-configurations/unpackrat-build-tests-license-package-configurations.yml b/.ort/package-configurations/unpackrat-build-tests-license-package-configurations.yml index 9d3eb8d..918a4ef 100644 --- a/.ort/package-configurations/unpackrat-build-tests-license-package-configurations.yml +++ b/.ort/package-configurations/unpackrat-build-tests-license-package-configurations.yml @@ -1,51 +1,51 @@ { - "id": "SpdxDocumentFile:vcpkg:unpackrat-build-tests-license-package-configurations:aa34ef18c34a9804f5fd8c6f581832855738888211699fe83c2e5a1e67dc5bd3", - "source_artifact_url": "http://127.0.0.1:8765/sources/aa34ef18c34a9804f5fd8c6f581832855738888211699fe83c2e5a1e67dc5bd3.tar", + "id": "SpdxDocumentFile:vcpkg:unpackrat-build-tests-license-package-configurations:47c9335cf1ef63875cf2c2402c81b9c3ac47d9e0ac4068674f51cabfbd014b6b", + "source_artifact_url": "http://127.0.0.1:8765/sources/47c9335cf1ef63875cf2c2402c81b9c3ac47d9e0ac4068674f51cabfbd014b6b.tar", "license_finding_curations": [ { "path": "build/tests/test_license_package_configurations.py", - "start_lines": "311,399,533,535,539,541,560,564", + "start_lines": "315,403,537,539,543,545,564,568", "line_count": 1, "detected_license": "GPL-1.0-or-later", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Lines 311,399,533,535,539,541,560,564 share the identifier GPL-1.0-or-later; line 311 is, for example, `\"detected_license\": \"GPL-1.0-or-later\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." + "comment": "Lines 315,403,537,539,543,545,564,568 share the identifier GPL-1.0-or-later; line 315 is, for example, `\"detected_license\": \"GPL-1.0-or-later\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." }, { "path": "build/tests/test_license_package_configurations.py", - "start_lines": "279,320,336,350,536,538,542,544,587,596,604,662", + "start_lines": "283,324,340,354,540,542,546,548,591,600,608,666", "line_count": 1, "detected_license": "GPL-2.0-only", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Lines 279,320,336,350,536,538,542,544,587,596,604,662 share the identifier GPL-2.0-only; line 279 is, for example, `\"detected_license\": \"GPL-2.0-only OR Apache-2.0\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." + "comment": "Lines 283,324,340,354,540,542,546,548,591,600,608,666 share the identifier GPL-2.0-only; line 283 is, for example, `\"detected_license\": \"GPL-2.0-only OR Apache-2.0\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." }, { "path": "build/tests/test_license_package_configurations.py", - "start_lines": "329,343,357,404", + "start_lines": "333,347,361,408", "line_count": 1, "detected_license": "GPL-2.0-or-later", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Lines 329,343,357,404 share the identifier GPL-2.0-or-later; line 329 is, for example, `\"detected_license\": \"GPL-2.0-or-later\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." + "comment": "Lines 333,347,361,408 share the identifier GPL-2.0-or-later; line 333 is, for example, `\"detected_license\": \"GPL-2.0-or-later\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." }, { "path": "build/tests/test_license_package_configurations.py", - "start_lines": "540", + "start_lines": "544", "line_count": 1, "detected_license": "GPL-3.0-only", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Line 540 carries `\"line_count\": 1, \"detected_license\": \"GPL-3.0-only\"},`. This first-party MIT build/test file holds the identifier only as the exact string it exercises or documents, not a grant; ScanCode reported GPL-3.0-only as a false positive, so the finding is removed." + "comment": "Line 544 carries `\"line_count\": 1, \"detected_license\": \"GPL-3.0-only\"},`. This first-party MIT build/test file holds the identifier only as the exact string it exercises or documents, not a grant; ScanCode reported GPL-3.0-only as a false positive, so the finding is removed." }, { "path": "build/tests/test_license_package_configurations.py", - "start_lines": "287,305,312,358,388", + "start_lines": "291,309,316,362,392", "line_count": 1, "detected_license": "LicenseRef-scancode-unknown", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Lines 287,305,312,358,388 share the identifier LicenseRef-scancode-unknown; line 287 is, for example, `\"concluded_license\": \"NONE\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." + "comment": "Lines 291,309,316,362,392 share the identifier LicenseRef-scancode-unknown; line 291 is, for example, `\"concluded_license\": \"NONE\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." } ] } diff --git a/build/license-inventory.json b/build/license-inventory.json index 77ae96b..2d231f8 100644 --- a/build/license-inventory.json +++ b/build/license-inventory.json @@ -379,18 +379,18 @@ "packaged": true, "incorporated": true, "declaredExpression": "MIT", - "version": "1.2.0", + "version": "1.2.1", "vcpkgName": "brotli", "source": { "origin": "registry", "recipe": "ports/brotli/portfile.cmake", "patches": [], - "url": "https://github.com/google/brotli/archive/v1.2.0.tar.gz", + "url": "https://github.com/google/brotli/archive/v1.2.1.tar.gz", "sha512": [ - "f94542afd2ecd96cc41fd21a805a3da314281ae558c10650f3e6d9ca732b8425bba8fde312823f0a564c7de3993bdaab5b43378edab65ebb798cefb6fd702256" + "460591287d428c8b5a8a2766b5b424d14501fcda12c7118b8f3cc4bfae44b90ac75ca156557f07b6e22542612724d904533e5f70019be07dbbb604c46f03ab69" ], "sha256": [ - "816c96e8e8f193b40151dad7e8ff37b1221d019dbcb9c35cd3fadbfe6477dfec" + "98d35d11a78dc453aebb7d10c3748f3f73ff78c8267c0dc697b8631f67bf7e8f" ], "identity": "github.com/google/brotli" }, @@ -599,8 +599,8 @@ "build/vcpkg/ports/drlibs/copyright": "8b2a772e9b30885997130bc8e0cfb07c238990fa433078649d251a1c5c7a3f64", "build/vcpkg/ports/drlibs/dr_mp3.c": "8a8f7911b316379d64400787abc871a61c2f76116e709a3e5b7001e77205af9f", "build/vcpkg/ports/drlibs/dr_wav.c": "550460509d1236e7ae85726f2e63511d76cef764b2730c8ead2c15a7bf0eba0e", - "build/vcpkg/ports/drlibs/portfile.cmake": "47acd54ed599ee14af582bf3f3831dff584b0a9f6f6fe128bfc8d5d66bbe1808", - "build/vcpkg/ports/drlibs/vcpkg.json": "76d471f45ecd9c537972820fa277bf806e5f5be289f1e5c1d687cf7b4c8f0090", + "build/vcpkg/ports/drlibs/portfile.cmake": "eaedc25792c12f5d8b6c02b1c16cbf15d0846badc350afeb28ba22837db35db2", + "build/vcpkg/ports/drlibs/vcpkg.json": "bf6b85a1610206a1ca4ed83ed759ffef0d10f66e4aa32c842c5b827afbe6f6ec", "build/vcpkg/triplets/unpackrat-x86-windows-static.cmake": "7f706840bc922781120cbd607e0f5a6008f0562e2178f9127f7bc8ea7d5754ab", "build/vcpkg/triplets/unpackrat-x64-windows-static.cmake": "e198af9bb1ccf802c74357faf1b90c2c808694112007dc71cc27fe10f21be6d7" }, @@ -612,20 +612,20 @@ "incorporated": true, "declaredExpression": "(Unlicense OR MIT-0)", "licenseChoice": null, - "version": "2026-08-31", + "version": "2026-11-11", "vcpkgName": "drlibs", "source": { "origin": "overlay", "recipe": "build/vcpkg/ports/drlibs/portfile.cmake", "patches": [], - "url": "https://github.com/mackron/dr_libs/blob/dfe8377631000664666519fdb83da193fd8037f4/dr_mp3.h", + "url": "https://github.com/mackron/dr_libs/blob/f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c/dr_mp3.h", "sha512": [ - "c21d523bdd890bf8b2e84ff7ac63f72299b235834b424d95d281b57c4e22d260e23e423ed8d829e710cbd11d8814c69afef24cb9e576bbb9cb0b704be94bf8ed", - "277ada6b7cf940f557d38dea7985db129c8aaf034c23425da3f1681e901439bbd4152a766de5a26cc7ddb3f0a00f2ce8f6496f61c359bc65889eeac25e356bd3" + "d31c0161928d7e3c2158b9a79a8db2b1ac37b8c81d4087ea499bb37f6b2591e6922e1288ae12047907da8c91ee828832f968b7cff44f8fd81e681a7b69ccbde9", + "88a622fa07f7bea5a4467340743ee20c7987170a2dba7579a5f44aff2d5e24ce73d9294cf591df8740df4bba6b64dc9ee18e5a21173b54ba72e649175c91e255" ], "sha256": [ - "997b7ee18de6e6b81e2a83f1ea9fc62aef25c62b28d48db95635f49e65de0a2f", - "03e70c1a2d9787cd7ed3e966c075bea7bac6373f759db9cd7ca9ccdfc4ec4493" + "7a6cc38b0afdb55cfc9eec991d9169d67beb8fd910be2995121510cdaa99c356", + "7c9660d75361ad6175e6217c63a1075c9512445c06bc951197fc479179f76b39" ], "identity": "github.com/mackron/dr_libs" }, diff --git a/build/tests/fixtures/license_package_configurations/expected_artifacts.json b/build/tests/fixtures/license_package_configurations/expected_artifacts.json index 80a7ef1..fda3ea3 100644 --- a/build/tests/fixtures/license_package_configurations/expected_artifacts.json +++ b/build/tests/fixtures/license_package_configurations/expected_artifacts.json @@ -11,7 +11,8 @@ "download name rather than the shortened name an earlier manual audit used. The", "header bytes are identical between the shortened and the real bundles, so the", "reviewed scan line matches are unchanged; only the member name and the resulting", - "deterministic tar hash differ." + "deterministic tar hash differ.", + "Brotli1.2.1 and drlibs2026-11-11 identities were renewed2026-11-12 from verified official source bytes; scanner observations remain historical and current test expectations are explicitly labelled derived." ], "components": [ { @@ -31,9 +32,9 @@ }, { "name": "brotli", - "version": "1.2.0", - "sha256": "816c96e8e8f193b40151dad7e8ff37b1221d019dbcb9c35cd3fadbfe6477dfec", - "artifact_filename": "816c96e8e8f193b40151dad7e8ff37b1221d019dbcb9c35cd3fadbfe6477dfec.tar.gz", + "version": "1.2.1", + "sha256": "98d35d11a78dc453aebb7d10c3748f3f73ff78c8267c0dc697b8631f67bf7e8f", + "artifact_filename": "98d35d11a78dc453aebb7d10c3748f3f73ff78c8267c0dc697b8631f67bf7e8f.tar.gz", "extension": ".tar.gz" }, { @@ -45,9 +46,9 @@ }, { "name": "drlibs", - "version": "2026-08-31", - "sha256": "a57b4c054240bf7debd9fd58ecae8f47d55cae2addd0eee6c5a6569b3cec6f34", - "artifact_filename": "a57b4c054240bf7debd9fd58ecae8f47d55cae2addd0eee6c5a6569b3cec6f34.tar", + "version": "2026-11-11", + "sha256": "aa971fb36a7a147157e7726ec2311e1d46bd2d3cc80ce70efebdda9ce61e807a", + "artifact_filename": "aa971fb36a7a147157e7726ec2311e1d46bd2d3cc80ce70efebdda9ce61e807a.tar", "extension": ".tar", "bundle": true }, diff --git a/build/tests/fixtures/license_package_configurations/firstparty_artifacts.json b/build/tests/fixtures/license_package_configurations/firstparty_artifacts.json index c8d5d25..ba18330 100644 --- a/build/tests/fixtures/license_package_configurations/firstparty_artifacts.json +++ b/build/tests/fixtures/license_package_configurations/firstparty_artifacts.json @@ -82,19 +82,19 @@ { "name": "unpackrat-build-tests-godot-minimal-registration", "member": "build/tests/test_godot_minimal_registration.py", - "version": "d213197f852ae31709506a4cbcfbbf9f86b051fd12061aa3c204642fc510aadc", - "sha256": "d213197f852ae31709506a4cbcfbbf9f86b051fd12061aa3c204642fc510aadc", - "artifact_filename": "d213197f852ae31709506a4cbcfbbf9f86b051fd12061aa3c204642fc510aadc.tar", + "version": "6cf4db24494dd28bc7d3b323ed7e335851eb22fb9a88e29e1d98ade2c0d4bff3", + "sha256": "6cf4db24494dd28bc7d3b323ed7e335851eb22fb9a88e29e1d98ade2c0d4bff3", + "artifact_filename": "6cf4db24494dd28bc7d3b323ed7e335851eb22fb9a88e29e1d98ade2c0d4bff3.tar", "extension": ".tar", "curations": [ { "path": "build/tests/test_godot_minimal_registration.py", - "start_lines": "69,87,217", + "start_lines": "70,88,218", "line_count": 1, "detected_license": "GPL-3.0-only", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Lines 69,87,217 share the identifier GPL-3.0-only; line 69 is, for example, `\"GPL-3.0.txt\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." + "comment": "Lines 70,88,218 share the identifier GPL-3.0-only; line 70 is, for example, `\"GPL-3.0.txt\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." } ] }, @@ -148,55 +148,55 @@ { "name": "unpackrat-build-tests-license-package-configurations", "member": "build/tests/test_license_package_configurations.py", - "version": "aa34ef18c34a9804f5fd8c6f581832855738888211699fe83c2e5a1e67dc5bd3", - "sha256": "aa34ef18c34a9804f5fd8c6f581832855738888211699fe83c2e5a1e67dc5bd3", - "artifact_filename": "aa34ef18c34a9804f5fd8c6f581832855738888211699fe83c2e5a1e67dc5bd3.tar", + "version": "47c9335cf1ef63875cf2c2402c81b9c3ac47d9e0ac4068674f51cabfbd014b6b", + "sha256": "47c9335cf1ef63875cf2c2402c81b9c3ac47d9e0ac4068674f51cabfbd014b6b", + "artifact_filename": "47c9335cf1ef63875cf2c2402c81b9c3ac47d9e0ac4068674f51cabfbd014b6b.tar", "extension": ".tar", "curations": [ { "path": "build/tests/test_license_package_configurations.py", - "start_lines": "311,399,533,535,539,541,560,564", + "start_lines": "315,403,537,539,543,545,564,568", "line_count": 1, "detected_license": "GPL-1.0-or-later", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Lines 311,399,533,535,539,541,560,564 share the identifier GPL-1.0-or-later; line 311 is, for example, `\"detected_license\": \"GPL-1.0-or-later\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." + "comment": "Lines 315,403,537,539,543,545,564,568 share the identifier GPL-1.0-or-later; line 315 is, for example, `\"detected_license\": \"GPL-1.0-or-later\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." }, { "path": "build/tests/test_license_package_configurations.py", - "start_lines": "279,320,336,350,536,538,542,544,587,596,604,662", + "start_lines": "283,324,340,354,540,542,546,548,591,600,608,666", "line_count": 1, "detected_license": "GPL-2.0-only", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Lines 279,320,336,350,536,538,542,544,587,596,604,662 share the identifier GPL-2.0-only; line 279 is, for example, `\"detected_license\": \"GPL-2.0-only OR Apache-2.0\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." + "comment": "Lines 283,324,340,354,540,542,546,548,591,600,608,666 share the identifier GPL-2.0-only; line 283 is, for example, `\"detected_license\": \"GPL-2.0-only OR Apache-2.0\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." }, { "path": "build/tests/test_license_package_configurations.py", - "start_lines": "329,343,357,404", + "start_lines": "333,347,361,408", "line_count": 1, "detected_license": "GPL-2.0-or-later", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Lines 329,343,357,404 share the identifier GPL-2.0-or-later; line 329 is, for example, `\"detected_license\": \"GPL-2.0-or-later\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." + "comment": "Lines 333,347,361,408 share the identifier GPL-2.0-or-later; line 333 is, for example, `\"detected_license\": \"GPL-2.0-or-later\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." }, { "path": "build/tests/test_license_package_configurations.py", - "start_lines": "540", + "start_lines": "544", "line_count": 1, "detected_license": "GPL-3.0-only", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Line 540 carries `\"line_count\": 1, \"detected_license\": \"GPL-3.0-only\"},`. This first-party MIT build/test file holds the identifier only as the exact string it exercises or documents, not a grant; ScanCode reported GPL-3.0-only as a false positive, so the finding is removed." + "comment": "Line 544 carries `\"line_count\": 1, \"detected_license\": \"GPL-3.0-only\"},`. This first-party MIT build/test file holds the identifier only as the exact string it exercises or documents, not a grant; ScanCode reported GPL-3.0-only as a false positive, so the finding is removed." }, { "path": "build/tests/test_license_package_configurations.py", - "start_lines": "287,305,312,358,388", + "start_lines": "291,309,316,362,392", "line_count": 1, "detected_license": "LicenseRef-scancode-unknown", "reason": "INCORRECT", "concluded_license": "NONE", - "comment": "Lines 287,305,312,358,388 share the identifier LicenseRef-scancode-unknown; line 287 is, for example, `\"concluded_license\": \"NONE\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." + "comment": "Lines 291,309,316,362,392 share the identifier LicenseRef-scancode-unknown; line 291 is, for example, `\"concluded_license\": \"NONE\",`. These are example literals in first-party MIT build/test tooling, not grants, so the false-positive finding is removed." } ] }, diff --git a/build/tests/fixtures/license_package_configurations/native_dependency_expectations.json b/build/tests/fixtures/license_package_configurations/native_dependency_expectations.json new file mode 100644 index 0000000..9c92cd4 --- /dev/null +++ b/build/tests/fixtures/license_package_configurations/native_dependency_expectations.json @@ -0,0 +1,101 @@ +{ + "evidence_kind": "test-only-derived-expectations-not-a-scan", + "description": "Historical raw observations stay unchanged. These exactly three expectations retarget only package/path after source-text identity review. A fresh scanner result must still be obtained in normal CI.", + "historical_fixture_sha256": "38918b612be77e76d6978ec72b35ddb0b3060b11360c029a5ff25b5af5dbcc21", + "mappings": [ + { + "historical": { + "package": "brotli", + "path": "brotli-1.2.0/CONTRIBUTING.md", + "start_lines": 31, + "end_lines": 31, + "license": "NOASSERTION", + "disposition": "excluded" + }, + "target": { + "package": "brotli", + "path": "brotli-1.2.1/CONTRIBUTING.md" + }, + "source_proof": "brotli-contributing" + }, + { + "historical": { + "package": "drlibs", + "path": "dr_libs-dfe8377631000664666519fdb83da193fd8037f4-dr_mp3.h", + "start_lines": 2, + "end_lines": 2, + "license": "LicenseRef-scancode-unknown-license-reference", + "disposition": "curated" + }, + "target": { + "package": "drlibs", + "path": "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_mp3.h" + }, + "source_proof": "mp3-line2" + }, + { + "historical": { + "package": "drlibs", + "path": "dr_libs-dfe8377631000664666519fdb83da193fd8037f4-dr_wav.h", + "start_lines": 2, + "end_lines": 2, + "license": "LicenseRef-scancode-unknown-license-reference", + "disposition": "curated" + }, + "target": { + "package": "drlibs", + "path": "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_wav.h" + }, + "source_proof": "wav-line2" + } + ], + "protected_prefixes": [ + { + "package": "brotli", + "historical": "brotli-1.2.0/", + "target": "brotli-1.2.1/", + "source_proof": "brotli-contributing" + } + ], + "source_proofs": { + "brotli-contributing": { + "package": "brotli", + "old_version": "1.2.0", + "new_version": "1.2.1", + "old_artifact_sha256": "816c96e8e8f193b40151dad7e8ff37b1221d019dbcb9c35cd3fadbfe6477dfec", + "new_artifact_sha256": "98d35d11a78dc453aebb7d10c3748f3f73ff78c8267c0dc697b8631f67bf7e8f", + "scoped_text_sha256": "805600c3f5808eb7fc8beb6f7768d5004ea700c99e8cdd7024eda7613f36e618", + "scope": "Entire CONTRIBUTING.md; byte-identical across the two official releases, including line31.", + "old_source": "https://github.com/google/brotli/blob/v1.2.0/CONTRIBUTING.md", + "new_source": "https://github.com/google/brotli/blob/v1.2.1/CONTRIBUTING.md", + "proof_report": "outputs/dependency-updates-20261112/brotli-source-identity.json" + }, + "mp3-line2": { + "package": "drlibs", + "old_version": "2026-08-31", + "new_version": "2026-11-11", + "old_artifact_sha256": "a57b4c054240bf7debd9fd58ecae8f47d55cae2addd0eee6c5a6569b3cec6f34", + "new_artifact_sha256": "aa971fb36a7a147157e7726ec2311e1d46bd2d3cc80ce70efebdda9ce61e807a", + "scoped_text_sha256": "941157d711e68ef2cec2f4ef215dae4a58d07dc88b4fd0178f650f8af93e43df", + "grant_footer_sha256": "6e9f945406227d3b8a6acee25eabd2ce5dc79b5c1bfab8c43fdb80bc38e25445", + "scope": "Line2 without its line terminator and retained complete grant footer are independently byte-identical.", + "old_source": "https://github.com/mackron/dr_libs/blob/dfe8377631000664666519fdb83da193fd8037f4/dr_mp3.h", + "new_source": "https://github.com/mackron/dr_libs/blob/f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c/dr_mp3.h", + "proof_report": "outputs/dependency-updates-20261112/dr-libs-curation-text-proof.json" + }, + "wav-line2": { + "package": "drlibs", + "old_version": "2026-08-31", + "new_version": "2026-11-11", + "old_artifact_sha256": "a57b4c054240bf7debd9fd58ecae8f47d55cae2addd0eee6c5a6569b3cec6f34", + "new_artifact_sha256": "aa971fb36a7a147157e7726ec2311e1d46bd2d3cc80ce70efebdda9ce61e807a", + "scoped_text_sha256": "6b49d692483ac0d50d3a3db3c39673c19c87b31865510fc69ab9d239f5f72f0e", + "grant_footer_sha256": "bd4b418451619e6a073314e61c30e06ab6c91edc4b854fbff1b8c7d5a552ae24", + "scope": "Line2 without its line terminator and retained complete grant footer are independently byte-identical.", + "old_source": "https://github.com/mackron/dr_libs/blob/dfe8377631000664666519fdb83da193fd8037f4/dr_wav.h", + "new_source": "https://github.com/mackron/dr_libs/blob/f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c/dr_wav.h", + "proof_report": "outputs/dependency-updates-20261112/dr-libs-curation-text-proof.json" + } + }, + "negative_control_license": "GPL-3.0-only" +} diff --git a/build/tests/fixtures/license_package_configurations/verified_header_snapshots.json b/build/tests/fixtures/license_package_configurations/verified_header_snapshots.json new file mode 100644 index 0000000..00e117d --- /dev/null +++ b/build/tests/fixtures/license_package_configurations/verified_header_snapshots.json @@ -0,0 +1,40 @@ +{ + "provenance": "Verified2026-11-12 from exact upstream header blobs read in memory; deterministic_tar reproduced the previous reviewed bundle hash before computing the new address. This is source-identity data, not a scanner observation or a claim of old CI output.", + "components": [ + { + "name": "drlibs", + "version": "2026-11-11", + "id": "SpdxDocumentFile:vcpkg:drlibs:2026-11-11", + "sha256": "aa971fb36a7a147157e7726ec2311e1d46bd2d3cc80ce70efebdda9ce61e807a", + "artifact_filename": "aa971fb36a7a147157e7726ec2311e1d46bd2d3cc80ce70efebdda9ce61e807a.tar", + "source_artifact_url": "http://127.0.0.1:8765/sources/aa971fb36a7a147157e7726ec2311e1d46bd2d3cc80ce70efebdda9ce61e807a.tar", + "members": [ + { + "path": "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_mp3.h", + "size": 203953, + "sha256": "7a6cc38b0afdb55cfc9eec991d9169d67beb8fd910be2995121510cdaa99c356", + "sha512": "d31c0161928d7e3c2158b9a79a8db2b1ac37b8c81d4087ea499bb37f6b2591e6922e1288ae12047907da8c91ee828832f968b7cff44f8fd81e681a7b69ccbde9" + }, + { + "path": "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_wav.h", + "size": 348779, + "sha256": "7c9660d75361ad6175e6217c63a1075c9512445c06bc951197fc479179f76b39", + "sha512": "88a622fa07f7bea5a4467340743ee20c7987170a2dba7579a5f44aff2d5e24ce73d9294cf591df8740df4bba6b64dc9ee18e5a21173b54ba72e649175c91e255" + } + ], + "resources": [ + { + "name": "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_mp3.h", + "url": "https://raw.githubusercontent.com/mackron/dr_libs/f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c/dr_mp3.h", + "sha512": "d31c0161928d7e3c2158b9a79a8db2b1ac37b8c81d4087ea499bb37f6b2591e6922e1288ae12047907da8c91ee828832f968b7cff44f8fd81e681a7b69ccbde9" + }, + { + "name": "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_wav.h", + "url": "https://raw.githubusercontent.com/mackron/dr_libs/f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c/dr_wav.h", + "sha512": "88a622fa07f7bea5a4467340743ee20c7987170a2dba7579a5f44aff2d5e24ce73d9294cf591df8740df4bba6b64dc9ee18e5a21173b54ba72e649175c91e255" + } + ] + } + ], + "historical_snapshot_sha256": "e8ef1ca469a5e52ed902c166559f748be5bc7c68d09e22ddb9f285478171b589" +} diff --git a/build/tests/native_dependency_expectations.py b/build/tests/native_dependency_expectations.py new file mode 100644 index 0000000..4f9cc3b --- /dev/null +++ b/build/tests/native_dependency_expectations.py @@ -0,0 +1,38 @@ +"""Apply only the reviewed test-data retargeting; never claim a new scan.""" +from __future__ import annotations + +from copy import deepcopy + + +def expectation_path_for_raw_record(record: dict, updates: dict) -> str: + for change in updates["mappings"]: + old = change["historical"] + if (all(record[field] == old[field] for field in ("package", "path", "start_lines", "end_lines")) + and record["raw_expression"] == old["license"]): + return change["target"]["path"] + return record["path"] + + +def derive_native_findings(historical: dict, updates: dict) -> dict: + if updates["evidence_kind"] != "test-only-derived-expectations-not-a-scan" or len(updates["mappings"]) != 3: + raise ValueError("Expected exactly three reviewed derived expectations.") + result = deepcopy(historical) + for change in updates["mappings"]: + if set(change["target"]) != {"package", "path"}: + raise ValueError("A mapping may change only package and path.") + matches = [row for row in result["findings"] if row == change["historical"]] + if len(matches) != 1: + raise ValueError("A mapping requires one exact historical observation.") + matches[0].update(change["target"]) + for change in updates["protected_prefixes"]: + package, before, after = change["package"], change["historical"], change["target"] + if result["prefixes"][package] != before: + raise ValueError("The historical protected prefix changed.") + result["prefixes"][package] = after + for row in result["protected"]: + if row["package"] == package: + if not row["path"].startswith(before): + raise ValueError("A protected path escaped its historical prefix.") + row["path"] = after + row["path"][len(before):] + result["evidence_kind"] = updates["evidence_kind"] + return result diff --git a/build/tests/test_dependency_updates.py b/build/tests/test_dependency_updates.py index 70dbc26..6847f3e 100644 --- a/build/tests/test_dependency_updates.py +++ b/build/tests/test_dependency_updates.py @@ -14,6 +14,24 @@ class DependencyUpdateTests(unittest.TestCase): + def test_brotli_requires_the_fixed_decoder_release(self) -> None: + manifest = json.loads((REPOSITORY / "vcpkg.json").read_text(encoding="utf-8")) + brotli = next(entry for entry in manifest["dependencies"] if entry["name"] == "brotli") + self.assertEqual(brotli["version>="], "1.2.1") + + def test_only_brotli_uses_the_exact_official_security_registry(self) -> None: + configuration = json.loads((REPOSITORY / "vcpkg-configuration.json").read_text(encoding="utf-8")) + self.assertEqual(configuration.get("registries", []), [{ + "kind": "git", + "repository": "https://github.com/microsoft/vcpkg", + "baseline": "61d7eaeb094a6acbc23d9c2e54de9208175fda47", + "reference": "61d7eaeb094a6acbc23d9c2e54de9208175fda47", + "packages": ["brotli"], + }]) + # Other packages continue using the manifest's qualified builtin baseline. + self.assertNotIn("default-registry", configuration) + self.assertFalse((PORTS / "brotli").exists()) + def test_overlay_patches_survive_a_fresh_git_checkout_without_crlf(self) -> None: patches = sorted(PORTS.rglob("*.patch")) self.assertGreaterEqual(len(patches), 2) diff --git a/build/tests/test_godot_minimal_registration.py b/build/tests/test_godot_minimal_registration.py index b0efb07..907c030 100644 --- a/build/tests/test_godot_minimal_registration.py +++ b/build/tests/test_godot_minimal_registration.py @@ -6,8 +6,8 @@ * Godot is a default module of the selection that drives the native audit and packaging routes (``main.MODULES`` / ``main.MODULE_BINARIES`` / ``main.LICENSES``); -* the default packaging route ships ``godot-1.2.1-bin-x64.zip``, - ``godot-1.2.1-bin-x86.zip`` and ``godot-1.2.1-pdb.zip`` with the shipped +* the default packaging route ships ``godot-1.2.2-bin-x64.zip``, + ``godot-1.2.2-bin-x86.zip`` and ``godot-1.2.2-pdb.zip`` with the shipped payload, registration and notices; * ``build/projects/tests.vcxproj`` references ``godot.vcxproj`` with the fixed project GUID and ``LinkLibraryDependencies=false``; @@ -24,6 +24,7 @@ from __future__ import annotations +import hashlib import json from pathlib import Path import re @@ -44,7 +45,7 @@ NS = {"msb": "http://schemas.microsoft.com/developer/msbuild/2003"} GODOT = "godot" -GODOT_VERSION = "1.2.1" +GODOT_VERSION = "1.2.2" GODOT_GUID = "{9C2F5E4A-7B31-4D58-8E27-1A6C4F0B9D34}" BASELINE = "9eec002df1cd109f8f104cd966a763daf9751489" WOLFRPG = "wolfrpg" @@ -581,17 +582,26 @@ def test_godot_xp_runtime_recipe_has_a_minor_version(self) -> None: self.assertEqual(main.read_version(REPOSITORY_ROOT, GODOT), GODOT_VERSION) def test_godot_runtime_recipe_reports_the_approved_release_history(self) -> None: + history_hashes = { + "en": "ec6241bebfd15e7d5a5c2525059241d3ed81cbc4b72236b0ee199ab911039fde", + "ru": "0efd4b69d15f85fd26e060ec08956848a1aaf084f5b47358f85dead7338367c1", + } + security_notes = { + "en": " * Fixed a vulnerability when processing Brotli-compressed resources.", + "ru": " * Исправлена уязвимость обработки ресурсов со сжатием Brotli.", + } for language in ("en", "ru"): with self.subTest(language=language): notes = (REPOSITORY_ROOT / f"src/modules/godot/ChangeLog.{language}.txt").read_text(encoding="utf-8") headers = list(re.finditer(r"^(?:Version|Версия)\s+(\S+)\s*$", notes, re.MULTILINE)) - self.assertEqual([header.group(1) for header in headers], ["1.2.1", "1.2.0", "1.0.0"]) + self.assertEqual([header.group(1) for header in headers], ["1.2.2", "1.2.1", "1.2.0", "1.0.0"]) top_block = notes[headers[0].end():headers[1].start()] - runtime_block, published_history = notes[headers[1].end():headers[2].start()], notes[headers[2].start():] - # The reviewed 1.2.1 patch leaves the 1.2.0 runtime block and the published - # 1.0.0 history intact, with their original four and eight entries. - self.assertEqual([len(re.findall(r"^ [+*] ", block, re.MULTILINE)) for block in (top_block, runtime_block)], [1, 4]) - self.assertEqual(len(re.findall(r"^ [+*] ", published_history, re.MULTILINE)), 8) + self.assertEqual([line for line in top_block.splitlines() if line.startswith(" * ")], + [security_notes[language]]) + # Every previously reviewed release section remains byte-identical after LF normalization. + published_history = notes[headers[1].start():] + self.assertEqual(hashlib.sha256(published_history.encode("utf-8")).hexdigest(), + history_hashes[language]) if __name__ == "__main__": # pragma: no cover diff --git a/build/tests/test_godot_overlay_ports.py b/build/tests/test_godot_overlay_ports.py index fb9a84d..d79ab55 100644 --- a/build/tests/test_godot_overlay_ports.py +++ b/build/tests/test_godot_overlay_ports.py @@ -10,7 +10,7 @@ REPOSITORY = Path(__file__).resolve().parents[2] PORTS = REPOSITORY / "build" / "vcpkg" / "ports" -# These are the exact headers exercised before the move out of third_party. +# These are the exact header snapshots qualified for the Godot adapters. HEADERS = { "bcdec": { "version": "0.985", @@ -20,11 +20,11 @@ }, }, "drlibs": { - "version": "2026-08-31", - "commit": "dfe8377631000664666519fdb83da193fd8037f4", + "version": "2026-11-11", + "commit": "f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c", "files": { - "dr_mp3.h": "c21d523bdd890bf8b2e84ff7ac63f72299b235834b424d95d281b57c4e22d260e23e423ed8d829e710cbd11d8814c69afef24cb9e576bbb9cb0b704be94bf8ed", - "dr_wav.h": "277ada6b7cf940f557d38dea7985db129c8aaf034c23425da3f1681e901439bbd4152a766de5a26cc7ddb3f0a00f2ce8f6496f61c359bc65889eeac25e356bd3", + "dr_mp3.h": "d31c0161928d7e3c2158b9a79a8db2b1ac37b8c81d4087ea499bb37f6b2591e6922e1288ae12047907da8c91ee828832f968b7cff44f8fd81e681a7b69ccbde9", + "dr_wav.h": "88a622fa07f7bea5a4467340743ee20c7987170a2dba7579a5f44aff2d5e24ce73d9294cf591df8740df4bba6b64dc9ee18e5a21173b54ba72e649175c91e255", }, }, "qoa": { diff --git a/build/tests/test_license_inventory.py b/build/tests/test_license_inventory.py index d5fe10a..2be571c 100644 --- a/build/tests/test_license_inventory.py +++ b/build/tests/test_license_inventory.py @@ -94,6 +94,29 @@ def test_every_vcpkg_component_records_a_stable_source_origin(self) -> None: if component["source"].get("url"): self.assertTrue(component["source"].get("identity")) + def test_brotli_inventory_binds_the_verified_security_archive(self) -> None: + component = next(row for row in self.document["components"] if row["name"] == "brotli") + self.assertEqual(component["version"], "1.2.1") + self.assertEqual(component["source"]["origin"], "registry") + self.assertEqual(component["source"]["url"], "https://github.com/google/brotli/archive/v1.2.1.tar.gz") + self.assertEqual(component["source"]["sha512"], [ + "460591287d428c8b5a8a2766b5b424d14501fcda12c7118b8f3cc4bfae44b90ac75ca156557f07b6e22542612724d904533e5f70019be07dbbb604c46f03ab69", + ]) + self.assertEqual(component["source"]["sha256"], [ + "98d35d11a78dc453aebb7d10c3748f3f73ff78c8267c0dc697b8631f67bf7e8f", + ]) + + def test_drlibs_inventory_binds_the_selected_snapshot_and_build_inputs(self) -> None: + component = next(row for row in self.document["components"] if row["name"] == "drlibs") + self.assertEqual(component["version"], "2026-11-11") + self.assertEqual(component["source"]["url"], + "https://github.com/mackron/dr_libs/blob/f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c/dr_mp3.h") + self.assertEqual(component["source"]["sha512"], [ + "d31c0161928d7e3c2158b9a79a8db2b1ac37b8c81d4087ea499bb37f6b2591e6922e1288ae12047907da8c91ee828832f968b7cff44f8fd81e681a7b69ccbde9", + "88a622fa07f7bea5a4467340743ee20c7987170a2dba7579a5f44aff2d5e24ce73d9294cf591df8740df4bba6b64dc9ee18e5a21173b54ba72e649175c91e255", + ]) + licenses._require_build_configuration("drlibs", component, ROOT) + class ObserverApiResolution(unittest.TestCase): """The one reviewed can't-fix resolution stays truthful and fail-closed. diff --git a/build/tests/test_license_package_configurations.py b/build/tests/test_license_package_configurations.py index 00c3836..5488d7e 100644 --- a/build/tests/test_license_package_configurations.py +++ b/build/tests/test_license_package_configurations.py @@ -5,9 +5,9 @@ artifact URL) to the scoped path excludes and license finding curations that were reviewed against the 2026-10-16 source audit. -Every archived source keeps its upstream top directory in the real ORT ScanCode -tree, so each path/pattern is anchored on that exact archive prefix (the -native_scan_findings fixture records the verified prefixes and the raw findings). +Every archived source keeps its upstream top directory, so each path/pattern is +anchored on that archive prefix. Raw scan fixtures stay historical; a separate, +source-verified test-only mapping labels current expectations without claiming a scan. """ import json @@ -15,6 +15,8 @@ import unittest from pathlib import Path +from native_dependency_expectations import derive_native_findings, expectation_path_for_raw_record + REPO_ROOT = Path(__file__).resolve().parents[2] CONFIG_DIR = REPO_ROOT / ".ort" / "package-configurations" FIXTURE_DIR = ( @@ -82,7 +84,9 @@ def load_scancode_evidence(): def load_native_findings(): - return json.loads(NATIVE_FINDINGS.read_text(encoding="utf-8")) + historical = json.loads(NATIVE_FINDINGS.read_text(encoding="utf-8")) + updates = json.loads((FIXTURE_DIR / "native_dependency_expectations.json").read_text(encoding="utf-8")) + return derive_native_findings(historical, updates) def find_config(configs, pkg_name): @@ -403,8 +407,8 @@ def test_only_documented_none_curations_remove_findings(self): 1625, "GPL-2.0-or-later", ), - ("drlibs", "dr_libs-dfe8377631000664666519fdb83da193fd8037f4-dr_mp3.h", 2, "LicenseRef-scancode-unknown-license-reference"), - ("drlibs", "dr_libs-dfe8377631000664666519fdb83da193fd8037f4-dr_wav.h", 2, "LicenseRef-scancode-unknown-license-reference"), + ("drlibs", "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_mp3.h", 2, "LicenseRef-scancode-unknown-license-reference"), + ("drlibs", "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_wav.h", 2, "LicenseRef-scancode-unknown-license-reference"), ("bcdec", "bcdec-80859ed3b7afb1c527a2a99d70c61457bea72d0c.h", 48, "LicenseRef-scancode-unknown-license-reference"), ( "zlib", @@ -428,7 +432,7 @@ def test_enumerated_scope_excludes_are_present(self): "mbedtls-4.1.1/tf-psa-crypto/drivers/pqcp/**", ], "libspng": ["libspng-0.7.4/tests/**"], - "brotli": ["brotli-1.2.0/CONTRIBUTING.md"], + "brotli": ["brotli-1.2.1/CONTRIBUTING.md"], } for pkg_name, patterns in expected.items(): config = next( @@ -488,8 +492,8 @@ def test_native_findings_use_the_verified_prefix(self): self.assertTrue(finding["path"].startswith(prefix)) self.assertIn(finding["disposition"], {"curated", "excluded"}) - def test_real_native_findings_are_covered(self): - """Each real evaluator finding is either curated or excluded as recorded.""" + def test_reviewed_native_expectations_are_covered(self): + """Historical observations and labelled derived cases keep exact coverage.""" for finding in self.native["findings"]: pkg_name = finding["package"] config = find_config(self.configs, pkg_name) @@ -536,7 +540,7 @@ def test_poisoned_native_findings_still_alert(self): "line_count": 1, "detected_license": "GPL-2.0-only"}, {"path": "bcdec-80859ed3b7afb1c527a2a99d70c61457bea72d0c.h", "start_lines": 1500, "line_count": 1, "detected_license": "GPL-2.0-only"}, - {"path": "brotli-1.2.0/c/enc/new_gpl.c", "start_lines": 1, + {"path": "brotli-1.2.1/c/enc/new_gpl.c", "start_lines": 1, "line_count": 1, "detected_license": "GPL-3.0-only"}, {"path": "mbedtls-4.1.1/library/new_gpl.c", "start_lines": 1, "line_count": 1, "detected_license": "GPL-2.0-only"}, @@ -567,15 +571,15 @@ def test_poisoned_native_findings_still_alert(self): def test_brotli_excludes_only_the_contribution_guide(self): config = find_config(self.configs, "brotli") patterns = [e["pattern"] for e in config.get("path_excludes", [])] - self.assertEqual(["brotli-1.2.0/CONTRIBUTING.md"], patterns) + self.assertEqual(["brotli-1.2.1/CONTRIBUTING.md"], patterns) excluded = next( e for e in config["path_excludes"] - if e["pattern"] == "brotli-1.2.0/CONTRIBUTING.md" + if e["pattern"] == "brotli-1.2.1/CONTRIBUTING.md" ) self.assertEqual("DOCUMENTATION_OF", excluded["reason"]) # The MIT source grants and the encoded library must stay scanned. - for path in ("brotli-1.2.0/LICENSE", "brotli-1.2.0/c/dec/decode.c", - "brotli-1.2.0/go/MODULE.bazel"): + for path in ("brotli-1.2.1/LICENSE", "brotli-1.2.1/c/dec/decode.c", + "brotli-1.2.1/go/MODULE.bazel"): with self.subTest(path=path): self.assertFalse(any(_ant_match(p, path) for p in patterns)) @@ -652,7 +656,7 @@ def test_scoped_exclude_validation(self): self.assertTrue(_is_scoped_exclude("tools/scripts/updateDocumentToC.py")) self.assertTrue(_is_scoped_exclude(".conan/**")) self.assertTrue(_is_scoped_exclude("Catch2-3.16.1/tools/**")) - self.assertTrue(_is_scoped_exclude("brotli-1.2.0/CONTRIBUTING.md")) + self.assertTrue(_is_scoped_exclude("brotli-1.2.1/CONTRIBUTING.md")) def test_curations_quote_the_complete_detected_expression(self): """A curation must match the whole raw ScanCode expression, not a token. @@ -665,6 +669,7 @@ def test_curations_quote_the_complete_detected_expression(self): curation with the complete expression. """ evidence = load_scancode_evidence()["records"] + updates = json.loads((FIXTURE_DIR / "native_dependency_expectations.json").read_text(encoding="utf-8")) self.assertTrue(evidence) for record in evidence: with self.subTest(package=record["package"], rule=record["rule"]): @@ -673,7 +678,7 @@ def test_curations_quote_the_complete_detected_expression(self): matching = [ c for c in config.get("license_finding_curations", []) - if c["path"] == record["path"] + if c["path"] == expectation_path_for_raw_record(record, updates) and c["start_lines"] == start and c["line_count"] == end - start + 1 and c["detected_license"] == record["raw_expression"] diff --git a/build/tests/test_native_dependency_expectations.py b/build/tests/test_native_dependency_expectations.py new file mode 100644 index 0000000..8bb1aa4 --- /dev/null +++ b/build/tests/test_native_dependency_expectations.py @@ -0,0 +1,132 @@ +"""Derived test expectations are distinct from preserved scanner observations.""" +from __future__ import annotations + +from copy import deepcopy +import hashlib +import json +from pathlib import Path +import unittest + +from native_dependency_expectations import derive_native_findings, expectation_path_for_raw_record +from test_license_package_configurations import curation_applies + +ROOT = Path(__file__).resolve().parents[2] +FIXTURES = Path(__file__).parent / "fixtures/license_package_configurations" + + +class NativeDependencyExpectations(unittest.TestCase): + def setUp(self) -> None: + self.raw_bytes = (FIXTURES / "native_scan_findings.json").read_bytes() + self.raw = json.loads(self.raw_bytes) + self.updates = json.loads((FIXTURES / "native_dependency_expectations.json").read_text(encoding="utf-8")) + + def test_exact_three_scoped_records_preserve_all_nonidentity_fields(self) -> None: + before = deepcopy(self.raw) + result = derive_native_findings(self.raw, self.updates) + self.assertEqual(self.raw, before) + self.assertEqual(hashlib.sha256(self.raw_bytes).hexdigest(), self.updates["historical_fixture_sha256"]) + self.assertEqual(len(self.updates["mappings"]), 3) + self.assertEqual(result["evidence_kind"], "test-only-derived-expectations-not-a-scan") + for original, actual in zip(self.raw["findings"], result["findings"], strict=True): + mapping = next((row for row in self.updates["mappings"] if row["historical"] == original), None) + expected = dict(original, **mapping["target"]) if mapping else original + self.assertEqual(actual, expected) + + def test_only_brotli_guard_paths_follow_the_new_source_prefix(self) -> None: + result = derive_native_findings(self.raw, self.updates) + self.assertEqual(result["prefixes"], dict(self.raw["prefixes"], brotli="brotli-1.2.1/")) + for original, actual in zip(self.raw["protected"], result["protected"], strict=True): + expected = dict(original) + if original["package"] == "brotli": + expected["path"] = original["path"].replace("brotli-1.2.0/", "brotli-1.2.1/", 1) + self.assertEqual(actual, expected) + + def test_unknown_license_path_or_line_is_never_retargeted_or_curated(self) -> None: + base = self.updates["mappings"][1]["historical"] + config = json.loads((ROOT / ".ort/package-configurations/drlibs.yml").read_text(encoding="utf-8")) + mutations = ({"license": self.updates["negative_control_license"]}, + {"path": base["path"] + ".new"}, {"start_lines": 3, "end_lines": 3}) + for mutation in mutations: + with self.subTest(mutation=mutation): + unexpected = dict(base, **mutation) + raw = deepcopy(self.raw) + raw["findings"].append(unexpected) + result = derive_native_findings(raw, self.updates) + self.assertEqual(result["findings"][-1], unexpected) + current = dict(base, **self.updates["mappings"][1]["target"]) + shape = dict(path=current["path"], start_lines=current["start_lines"], + line_count=current["end_lines"] - current["start_lines"] + 1, + detected_license=current["license"]) + self.assertTrue(any(curation_applies(row, shape) for row in config["license_finding_curations"])) + for mutation in ({"detected_license": self.updates["negative_control_license"]}, + {"path": shape["path"] + ".new"}, {"start_lines": 3}): + with self.subTest(current_mutation=mutation): + unknown = dict(shape, **mutation) + self.assertFalse(any(curation_applies(row, unknown) for row in config["license_finding_curations"])) + + def test_a_changed_or_duplicate_scoped_observation_requires_review(self) -> None: + for duplicate in (False, True): + with self.subTest(duplicate=duplicate): + raw = deepcopy(self.raw) + original = self.updates["mappings"][0]["historical"] + if duplicate: + raw["findings"].append(deepcopy(original)) + else: + next(row for row in raw["findings"] if row == original)["start_lines"] += 1 + with self.assertRaisesRegex(ValueError, "exact historical observation"): + derive_native_findings(raw, self.updates) + + def test_mapping_cannot_change_a_nonidentity_field(self) -> None: + updates = deepcopy(self.updates) + updates["mappings"][0]["target"]["license"] = updates["negative_control_license"] + with self.assertRaisesRegex(ValueError, "package and path"): + derive_native_findings(self.raw, updates) + + def test_changed_kind_count_or_protected_prefix_requires_review(self) -> None: + for changed in ("kind", "count", "prefix", "guard-path"): + with self.subTest(changed=changed): + updates = deepcopy(self.updates) + raw = deepcopy(self.raw) + if changed == "kind": + updates["evidence_kind"] = "observed-scan" + elif changed == "count": + updates["mappings"].pop() + elif changed == "prefix": + updates["protected_prefixes"][0]["historical"] = "unknown/" + else: + next(row for row in raw["protected"] if row["package"] == "brotli")["path"] = "unknown/file.c" + with self.assertRaises(ValueError): + derive_native_findings(raw, updates) + + def test_source_proofs_bind_the_active_real_artifact_identities(self) -> None: + artifacts = json.loads((FIXTURES / "expected_artifacts.json").read_text(encoding="utf-8")) + by_name = {row["name"]: row for row in artifacts["components"]} + self.assertEqual(set(self.updates["source_proofs"]), {"brotli-contributing", "mp3-line2", "wav-line2"}) + for proof in self.updates["source_proofs"].values(): + with self.subTest(proof=proof["new_source"]): + actual = by_name[proof["package"]] + self.assertEqual(actual["version"], proof["new_version"]) + self.assertEqual(actual["sha256"], proof["new_artifact_sha256"]) + self.assertRegex(proof["scoped_text_sha256"], r"^[0-9a-f]{64}$") + self.assertTrue(proof["proof_report"].startswith("outputs/dependency-updates-20261112/")) + + def test_raw_expression_records_keep_every_field_and_retarget_only_reviewed_text(self) -> None: + records = json.loads((FIXTURES / "scancode_evidence.json").read_text(encoding="utf-8"))["records"] + for record in records: + before = deepcopy(record) + matching = next((row for row in self.updates["mappings"] + if row["historical"]["package"] == record["package"] + and row["historical"]["path"] == record["path"]), None) + expected = matching["target"]["path"] if matching else record["path"] + self.assertEqual(expectation_path_for_raw_record(record, self.updates), expected) + self.assertEqual(record, before) + original = next(row for row in records if row["package"] == "drlibs") + for mutation in ({"raw_expression": self.updates["negative_control_license"]}, + {"path": original["path"] + ".new"}, {"start_lines": 3}): + with self.subTest(mutation=mutation): + unknown = dict(original, **mutation) + self.assertEqual(expectation_path_for_raw_record(unknown, self.updates), unknown["path"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/build/tests/test_real_header_bundles.py b/build/tests/test_real_header_bundles.py index 506be0c..9001e4a 100644 --- a/build/tests/test_real_header_bundles.py +++ b/build/tests/test_real_header_bundles.py @@ -23,6 +23,11 @@ and the artifact table carry the real names. The production red was proven by the primary against the real CLI archives; this unit fixture is a narrow selector and naming pin, not a claim of full end-to-end coverage. + +Later qualified snapshots use separately recorded upstream-byte identities from +verified_header_snapshots.json. The historical CI capture stays byte-for-byte +unchanged; neither those source calculations nor the current selectors claim a +new scanner observation. """ from __future__ import annotations @@ -61,11 +66,14 @@ def _bundle_members(data: bytes) -> list[str]: class ActualHeaderBundles(unittest.TestCase): - """The ORT selectors and the approved artifact table target the real bundles.""" + """Current selectors use verified bytes; the historical capture stays frozen.""" @classmethod def setUpClass(cls) -> None: - cls.actual = _load("actual_header_bundles.json") + cls.historical = _load("actual_header_bundles.json") + cls.snapshots = _load("verified_header_snapshots.json") + cls.current = {row["name"]: row for row in cls.historical["components"]} + cls.current.update({row["name"]: row for row in cls.snapshots["components"]}) cls.expected = { component["name"]: component for component in _load("expected_artifacts.json")["components"] @@ -74,8 +82,14 @@ def setUpClass(cls) -> None: def _configuration(self, name: str) -> dict: return json.loads((CONFIGURATIONS / f"{name}.yml").read_text(encoding="utf-8")) + def test_historical_capture_is_not_rewritten_as_a_new_observation(self) -> None: + raw = (FIXTURES / "actual_header_bundles.json").read_bytes() + self.assertEqual(hashlib.sha256(raw).hexdigest(), self.snapshots.get("historical_snapshot_sha256")) + self.assertEqual({row["name"] for row in self.snapshots["components"]}, {"drlibs"}) + self.assertIn("not a scanner observation", self.snapshots["provenance"]) + def test_approved_artifact_table_matches_the_real_bundles(self) -> None: - for component in self.actual["components"]: + for component in self.current.values(): name = component["name"] with self.subTest(component=name): approved = self.expected[name] @@ -86,7 +100,7 @@ def test_approved_artifact_table_matches_the_real_bundles(self) -> None: ) def test_configurations_address_the_real_artifact(self) -> None: - for component in self.actual["components"]: + for component in self.current.values(): name = component["name"] with self.subTest(component=name): configuration = self._configuration(name) @@ -96,7 +110,7 @@ def test_configurations_address_the_real_artifact(self) -> None: ) def test_curation_selectors_address_the_real_bundle_members(self) -> None: - for component in self.actual["components"]: + for component in self.current.values(): name = component["name"] with self.subTest(component=name): configuration = self._configuration(name) @@ -112,7 +126,7 @@ def test_production_naming_keeps_the_resource_download_filenames(self) -> None: "bcdec": b"bcdec tiny payload\n", "drlibs": b"dr_libs tiny payload\n", } - for component in self.actual["components"]: + for component in self.current.values(): name = component["name"] with self.subTest(component=name): payload = payloads[name] diff --git a/build/vcpkg/ports/README.md b/build/vcpkg/ports/README.md index 944dd7c..c7d75be 100644 --- a/build/vcpkg/ports/README.md +++ b/build/vcpkg/ports/README.md @@ -11,16 +11,16 @@ is retained in `licenses/YY-Thunks.txt`. ## Godot decoder overlays -The decoder ports build the exact single-header decoders that were tested for Godot 1.0.0. Each port +The decoder ports build the exact single-header snapshots qualified for the Godot adapters. Each port downloads only its pinned header files, checks their SHA-512 hashes, builds a static library for the selected vcpkg triplet and installs a copyright notice identical to the one packaged with Godot. -The header SHA-256 values below are the fingerprints of the former `third_party` copies; changing a +The header SHA-256 values below identify the selected upstream bytes; changing a revision requires a deliberate compatibility review and new codec tests. | Port | Source revision | Installed header SHA-256 | |------|-----------------|-------------------------| | bcdec 0.985 | [iOrange/bcdec `80859ed3b7afb1c527a2a99d70c61457bea72d0c`](https://github.com/iOrange/bcdec/tree/80859ed3b7afb1c527a2a99d70c61457bea72d0c) | `bcdec.h` `134520764d96f70a27db814173616c89ad85db95fbd3328417c7a8c77e7ca189` | -| drlibs (`dr_mp3` 0.7.4, `dr_wav` 0.14.6) | [mackron/dr_libs `dfe8377631000664666519fdb83da193fd8037f4`](https://github.com/mackron/dr_libs/tree/dfe8377631000664666519fdb83da193fd8037f4) | `dr_mp3.h` `997b7ee18de6e6b81e2a83f1ea9fc62aef25c62b28d48db95635f49e65de0a2f`; `dr_wav.h` `03e70c1a2d9787cd7ed3e966c075bea7bac6373f759db9cd7ca9ccdfc4ec4493` | +| drlibs (`dr_mp3` 0.7.5, `dr_wav` 0.14.7 snapshot) | [mackron/dr_libs `f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c`](https://github.com/mackron/dr_libs/tree/f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c) | `dr_mp3.h` `7a6cc38b0afdb55cfc9eec991d9169d67beb8fd910be2995121510cdaa99c356`; `dr_wav.h` `7c9660d75361ad6175e6217c63a1075c9512445c06bc951197fc479179f76b39` | | qoa | [Godot 4.7.2-stable `ed1daf0bf001b61586d9930840f2f1394092c079`](https://github.com/godotengine/godot/tree/ed1daf0bf001b61586d9930840f2f1394092c079) `thirdparty/misc/qoa.h` | `qoa.h` `ab501e91f4afd18c811e689713e5fd3956030562bf80cda784d304af17133f01` | The QOA port deliberately uses Godot's fork rather than the current phoboslab header. The `drlibs` @@ -29,6 +29,19 @@ package's notices remain in `licenses/bcdec.txt`, `licenses/dr_libs.txt` and `li The QOA header selected from Godot 4.7.2-stable is byte-identical to the previously tested 4.5-stable header (23,845 bytes); its download hashes, license and decoder behavior are unchanged. +The drlibs 2026-11-11 commit is an exact source snapshot: its headers label dr_mp3 0.7.5 +as unreleased and dr_wav 0.14.7 as pending. Both headers and their static library are rebuilt +together; the Godot first-frame MP3 probe and PCM16 WAV writer keep their existing contracts. + +Brotli 1.2.1 comes from a package-specific Git registry in `vcpkg-configuration.json`. +Both its baseline and reference select the official vcpkg commit +`61d7eaeb094a6acbc23d9c2e54de9208175fda47`; all other packages keep the manifest's +builtin baseline. This reuses the official port without maintaining another overlay copy. +The build's source attestations include the registry configuration and the installed SPDX +records retain the actual recipe tree and upstream source checksum. Task-local restores +set `X_VCPKG_REGISTRIES_CACHE` to an existing directory inside the project alongside their +download and binary caches. + Catch2 3.16.1 and Mbed TLS 4.1.1 LTS are also pinned here while the registry trails these upstream releases. Catch2 retains the registry's static-library and manual-main packaging. The Mbed TLS port uses the complete official release archive, including TF-PSA-Crypto 1.1.1 and generated sources. diff --git a/build/vcpkg/ports/drlibs/portfile.cmake b/build/vcpkg/ports/drlibs/portfile.cmake index a8678c7..4105d3d 100644 --- a/build/vcpkg/ports/drlibs/portfile.cmake +++ b/build/vcpkg/ports/drlibs/portfile.cmake @@ -1,13 +1,13 @@ # Keep both adapters on the exact tested dr_libs revision. vcpkg_download_distfile(DR_MP3_HEADER - URLS "https://raw.githubusercontent.com/mackron/dr_libs/dfe8377631000664666519fdb83da193fd8037f4/dr_mp3.h" - FILENAME "dr_libs-dfe8377631000664666519fdb83da193fd8037f4-dr_mp3.h" - SHA512 c21d523bdd890bf8b2e84ff7ac63f72299b235834b424d95d281b57c4e22d260e23e423ed8d829e710cbd11d8814c69afef24cb9e576bbb9cb0b704be94bf8ed + URLS "https://raw.githubusercontent.com/mackron/dr_libs/f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c/dr_mp3.h" + FILENAME "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_mp3.h" + SHA512 d31c0161928d7e3c2158b9a79a8db2b1ac37b8c81d4087ea499bb37f6b2591e6922e1288ae12047907da8c91ee828832f968b7cff44f8fd81e681a7b69ccbde9 ) vcpkg_download_distfile(DR_WAV_HEADER - URLS "https://raw.githubusercontent.com/mackron/dr_libs/dfe8377631000664666519fdb83da193fd8037f4/dr_wav.h" - FILENAME "dr_libs-dfe8377631000664666519fdb83da193fd8037f4-dr_wav.h" - SHA512 277ada6b7cf940f557d38dea7985db129c8aaf034c23425da3f1681e901439bbd4152a766de5a26cc7ddb3f0a00f2ce8f6496f61c359bc65889eeac25e356bd3 + URLS "https://raw.githubusercontent.com/mackron/dr_libs/f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c/dr_wav.h" + FILENAME "dr_libs-f12e197fd462e4c22873fbd70d11b1d2f2c1dc3c-dr_wav.h" + SHA512 88a622fa07f7bea5a4467340743ee20c7987170a2dba7579a5f44aff2d5e24ce73d9294cf591df8740df4bba6b64dc9ee18e5a21173b54ba72e649175c91e255 ) set(SOURCE_PATH "${CURRENT_BUILDTREES_DIR}/source") diff --git a/build/vcpkg/ports/drlibs/vcpkg.json b/build/vcpkg/ports/drlibs/vcpkg.json index 9081713..5ac5cbf 100644 --- a/build/vcpkg/ports/drlibs/vcpkg.json +++ b/build/vcpkg/ports/drlibs/vcpkg.json @@ -1,6 +1,6 @@ { "name": "drlibs", - "version-string": "2026-08-31", + "version-string": "2026-11-11", "description": "Pinned dr_mp3 and dr_wav single-header decoders used by the Godot module", "homepage": "https://github.com/mackron/dr_libs", "license": "Unlicense OR MIT-0", diff --git a/src/modules/godot/ChangeLog.en.txt b/src/modules/godot/ChangeLog.en.txt index ccb1290..b994413 100644 --- a/src/modules/godot/ChangeLog.en.txt +++ b/src/modules/godot/ChangeLog.en.txt @@ -1,3 +1,7 @@ +Version 1.2.2 +------------- + * Fixed a vulnerability when processing Brotli-compressed resources. + Version 1.2.1 ------------- * Shared Observer metadata handling now supports lazy indexed catalogues and rejects producer paths beyond the UTF-8 metadata length bound. diff --git a/src/modules/godot/ChangeLog.ru.txt b/src/modules/godot/ChangeLog.ru.txt index d4ed3c9..70c6b86 100644 --- a/src/modules/godot/ChangeLog.ru.txt +++ b/src/modules/godot/ChangeLog.ru.txt @@ -1,3 +1,7 @@ +Версия 1.2.2 +------------- + * Исправлена уязвимость обработки ресурсов со сжатием Brotli. + Версия 1.2.1 ------------- * Общая обработка метаданных Observer теперь поддерживает каталоги с отложенной индексацией и отклоняет превышающие ограничение UTF-8 пути, возвращаемые поставщиком. diff --git a/src/modules/godot/VERSION b/src/modules/godot/VERSION index 6085e94..23aa839 100644 --- a/src/modules/godot/VERSION +++ b/src/modules/godot/VERSION @@ -1 +1 @@ -1.2.1 +1.2.2 diff --git a/src/tests/unit/audio_io.cpp b/src/tests/unit/audio_io.cpp index feff685..7febc6e 100644 --- a/src/tests/unit/audio_io.cpp +++ b/src/tests/unit/audio_io.cpp @@ -144,6 +144,19 @@ namespace } } // namespace +TEST_CASE("audio: incomplete MP3 frames clear the decoder layer metadata", "[audio][mp3][dependency]") +{ + const std::array header{0xff, 0xfb, 0x90, 0x64}; + for (const int bytes : std::array{0, 1, 4}) { + const auto decoder = std::make_unique(); + drmp3dec_init(decoder.get()); + drmp3dec_frame_info info{}; + info.layer = 3; + CHECK(drmp3dec_decode_frame(decoder.get(), header.data(), bytes, nullptr, &info) == 0); + CHECK(info.layer == 0); + } +} + TEST_CASE("audio: mp3 silence decodes to a known rate, channel count and length") { const pcm_audio mono = decode_mp3(test::support::make_mp3_silence(4, false)); diff --git a/src/tests/unit/resource_compression.cpp b/src/tests/unit/resource_compression.cpp index 1e7418f..ff18752 100644 --- a/src/tests/unit/resource_compression.cpp +++ b/src/tests/unit/resource_compression.cpp @@ -13,8 +13,9 @@ #include #include -#ifdef _DEBUG #include + +#ifdef _DEBUG #include #include #define ZSTD_STATIC_LINKING_ONLY @@ -158,6 +159,11 @@ namespace } } // namespace +TEST_CASE("resource compression: links the qualified fixed Brotli decoder", "[godot][brotli-version]") +{ + CHECK(BrotliDecoderVersion() == 0x01002001U); +} + TEST_CASE("resource compression: round trips every mode with exact output") { const std::array sizes{1, 8, 16, 64, std::size_t{200} * 1024}; diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json index fda77fc..e771090 100644 --- a/vcpkg-configuration.json +++ b/vcpkg-configuration.json @@ -1,5 +1,14 @@ { "overlay-ports": [ "build/vcpkg/ports" + ], + "registries": [ + { + "kind": "git", + "repository": "https://github.com/microsoft/vcpkg", + "baseline": "61d7eaeb094a6acbc23d9c2e54de9208175fda47", + "reference": "61d7eaeb094a6acbc23d9c2e54de9208175fda47", + "packages": ["brotli"] + } ] } diff --git a/vcpkg.json b/vcpkg.json index 4ae0204..d457717 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -39,7 +39,7 @@ }, { "name": "brotli", - "version>=": "1.2.0" + "version>=": "1.2.1" }, { "name": "zstd",