test: finalize STEP-074 QBIN2 padding boundary
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# STEP-074 — QBIN2 V4 Encoded Ingress 与 Decoder v4
|
||||
|
||||
状态:完成
|
||||
|
||||
日期:2026-09-13
|
||||
|
||||
## 目标
|
||||
|
||||
仅修正 v3 `AcceptsRawLimitWithCanonicalPaddingExcluded` 的边界 fixture,使它严格证明 decoded raw 数据不超过 32 MiB、canonical packed payload 超过 32 MiB、整个 QBIN 文件不超过 64 MiB 时 production Decoder 仍接受。
|
||||
|
||||
## 基线
|
||||
|
||||
- 开始 HEAD:`f4a495ff38b77f586f97853493dda02ab067b26d`。
|
||||
- 开始前已有 STEP-062 文档修改及历史 untracked/build 文件;均未清理、覆盖、暂存或纳入本 Step。
|
||||
|
||||
## 必做项
|
||||
|
||||
- [x] `AcceptsRawLimitWithCanonicalPaddingExcluded` 改为 1101×1890(2,080,890 cells)、17 plane:1 个 single shared validity BITSET 与 16 个 UINT8 numeric plane;descriptor 依 semantic 3、4–19 canonical 排序。
|
||||
- [x] 测试直接计算并断言 `rawSum=33,554,352 <= 33,554,432`、`payloadLength=33,554,448 > 33,554,432`、`payloadLength > rawSum`、`totalQbinBytes=33,555,104 <= 67,108,864`。
|
||||
- [x] fixture 经 production `QbinV2Decoder::decode(...)` 返回 Accepted。
|
||||
- [x] cells、planes、canonical packing、single shared validity、descriptor 与 64 MiB 文件限制均在构造及断言内满足。
|
||||
|
||||
## 允许修改
|
||||
|
||||
- `test/particle/qbin_v2_decoder.test.cpp`。
|
||||
- 本 Step 记录、完成报告与粒子开发记录。
|
||||
|
||||
## 禁止修改
|
||||
|
||||
- Production Decoder、Host、网络、JNI、RN、Binding/Projection、Renderer、Store submission、Android/iOS 平台路径。
|
||||
|
||||
## 构建测试
|
||||
|
||||
- `cmake --build build-linux-opengl --target mbgl-test-runner -j3`:PASS(输出节流器;实际目标已重新检查并确认最新)。
|
||||
- `ParticleQbinV2Decoder.*:ParticleEncodedFieldIngress.*`:实际 Running 24,24/24 PASS(XML:Decoder 22、Ingress 2)。
|
||||
- `ParticleFieldRuntime.*:ParticleFieldProfileValidator.*`:实际 Running 11,11/11 PASS。
|
||||
- `Source.ParticleFieldDataAdapter*:Source.RasterArrayTimeline*:Source.HostField*`:实际 Running 11,11/11 PASS。
|
||||
- `git diff --check`:PASS。
|
||||
|
||||
## 当前结果
|
||||
|
||||
旧 fixture 的 payload 仍低于 32 MiB,不能捕获把 packed payload 误当 decoded raw limit 的实现错误。新 fixture 以 16 个每个 6-byte canonical padding 的 numeric plane 将 payload 推至 limit 以上 16 bytes,同时 raw sum 比 limit 小 80 bytes;production Decoder 接受,未发现生产缺陷,故未修改 production 代码。
|
||||
|
||||
## 阻塞与下一步
|
||||
|
||||
无范围内阻塞。未执行 Android Gradle/APK/ADB/Jest;按任务要求停止,不进入下一 Step。
|
||||
@@ -0,0 +1,31 @@
|
||||
# STEP-074 — QBIN2 V4 Encoded Ingress 与 Decoder Codex 完成报告 v4
|
||||
|
||||
日期:2026-09-13
|
||||
|
||||
## 结果
|
||||
|
||||
已完成:只更新 `test/particle/qbin_v2_decoder.test.cpp` 中的 `AcceptsRawLimitWithCanonicalPaddingExcluded` fixture。新的 1101×1890、17-plane canonical QBIN 的数值为:
|
||||
|
||||
- rawSum:33,554,352 bytes。
|
||||
- 32 MiB limit:33,554,432 bytes。
|
||||
- payloadLength:33,554,448 bytes。
|
||||
- totalQbinBytes:33,555,104 bytes。
|
||||
|
||||
测试直接断言 `rawSum <= limit`、`payloadLength > limit`、`payloadLength > rawSum` 与 `totalQbinBytes <= 64 MiB`,并调用 production `QbinV2Decoder::decode(...)`,结果 Accepted。
|
||||
|
||||
## 逐项状态
|
||||
|
||||
- 已完成:边界构造覆盖 canonical padding 将 payload 推过 32 MiB,而 decoded raw sum 未越界。
|
||||
- 已完成:cells=2,080,890(不超过 2,097,152),planes=17(不超过 32),single shared validity、descriptor 合法与 canonical packing 均成立。
|
||||
- 已完成:真实重建 `mbgl-test-runner`;Decoder/Ingress Running 24、Runtime/Profile Running 11、Source 回归 Running 11,均 PASS、零失败。
|
||||
- 已完成:`git diff --check` PASS。
|
||||
- 未完成:无。
|
||||
- 无法验证:Android Gradle/APK/ADB/Jest、iOS/Metal;本任务明确禁止执行,且本轮未涉及这些路径。
|
||||
|
||||
## 范围审计
|
||||
|
||||
未修改 production Decoder,未触及 Host、网络、JNI、RN、Binding/Projection、Renderer 或 Store submission。已有 STEP-062 修改及历史 untracked/build 文件原样保留。
|
||||
|
||||
## Git
|
||||
|
||||
- 首个 scoped commit、push 与最终 HEAD:待本报告的 Git 字段补写后执行 docs-only commit 并推送;不会暂存既有 STEP-062 修改、任务书或其他 untracked 文件。
|
||||
@@ -50,7 +50,36 @@ TEST(ParticleQbinV2Decoder, RejectsFrameAndReservedHeader) { auto b=fixture();u1
|
||||
TEST(ParticleQbinV2Decoder, RejectsGridTimeAndBounds) { auto b=fixture();u32(b,16,1);recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidHeader); b=fixture();u32(b,16,2049);u32(b,20,1024);recalc(b);EXPECT_EQ(decodeCode(b),Code::LimitExceeded); b=fixture();i64(b,24,0);recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidTime); b=fixture();i64(b,32,0);recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidTime); b=fixture();i64(b,24,std::numeric_limits<int64_t>::max());recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidTime); b=fixture();f64(b,40,std::numeric_limits<double>::quiet_NaN());recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidBounds); b=fixture();f64(b,40,11);recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidBounds); b=fixture();f64(b,48,86);recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidBounds); }
|
||||
TEST(ParticleQbinV2Decoder, RejectsLengthAndFileLimits) { auto b=fixture();b.pop_back();EXPECT_EQ(decodeCode(b),Code::LengthMismatch); b=fixture();b.push_back(0);EXPECT_EQ(decodeCode(b),Code::LengthMismatch); std::vector<uint8_t> huge(64u*1024u*1024u+1);EXPECT_EQ(decodeCode(huge),Code::LimitExceeded); }
|
||||
TEST(ParticleQbinV2Decoder, LimitsDecodedBytesWithoutChargingCanonicalPadding) { std::vector<P> ps={{3,0,0,6,1,3,0,1,0,{}}}; for(uint16_t semantic=4;semantic<13;++semantic) ps.push_back({semantic,77,0,5,0,0,0,1,0,{}}); EXPECT_EQ(decodeCode(fixture(1024,1024,ps)),Code::LimitExceeded); }
|
||||
TEST(ParticleQbinV2Decoder, AcceptsRawLimitWithCanonicalPaddingExcluded) { const uint32_t width=1447, height=1449; const uint64_t cells=uint64_t(width)*height; ASSERT_LE(cells, 2'097'152u); std::vector<P> ps={{3,0,0,6,1,3,0,1,0,{}}}; for(uint16_t semantic=4;semantic<7;++semantic) ps.push_back({semantic,77,0,5,0,0,0,1,0,{}}); for(uint16_t semantic=7;semantic<10;++semantic) ps.push_back({semantic,77,0,3,0,0,0,1,0,{}}); uint64_t rawSum=0; size_t payloadLength=0; for (const auto& p : ps) { const size_t bytes=rawLength(p.type,cells); rawSum+=bytes; payloadLength=a16(payloadLength+bytes); } EXPECT_LE(rawSum, 32u*1024u*1024u); EXPECT_GT(rawSum, 30u*1024u*1024u); EXPECT_GT(payloadLength, rawSum); auto b=fixture(width,height,ps); ASSERT_EQ(b.size(), Header+ps.size()*Descriptor+payloadLength); auto r=particle::ingress::QbinV2Decoder::decode(meta(),b); EXPECT_TRUE(r.accepted())<<r.detail; }
|
||||
TEST(ParticleQbinV2Decoder, AcceptsRawLimitWithCanonicalPaddingExcluded) {
|
||||
constexpr uint64_t limit = 32ull * 1024ull * 1024ull;
|
||||
const uint32_t width = 1101, height = 1890;
|
||||
const uint64_t cells = uint64_t(width) * height;
|
||||
ASSERT_LE(cells, 2'097'152u);
|
||||
|
||||
std::vector<P> ps = {{3, 0, 0, 6, 1, 3, 0, 1, 0, {}}};
|
||||
for (uint16_t semantic = 4; semantic < 20; ++semantic) {
|
||||
ps.push_back({semantic, 77, 0, 3, 0, 0, 0, 1, 0, {}});
|
||||
}
|
||||
|
||||
uint64_t rawSum = 0;
|
||||
uint64_t payloadLength = 0;
|
||||
for (const auto& p : ps) {
|
||||
const uint64_t bytes = rawLength(p.type, cells);
|
||||
rawSum += bytes;
|
||||
payloadLength = a16(payloadLength + bytes);
|
||||
}
|
||||
|
||||
auto b = fixture(width, height, ps);
|
||||
const uint64_t totalQbinBytes = b.size();
|
||||
EXPECT_LE(rawSum, limit);
|
||||
EXPECT_GT(payloadLength, limit);
|
||||
EXPECT_GT(payloadLength, rawSum);
|
||||
EXPECT_LE(totalQbinBytes, 64ull * 1024ull * 1024ull);
|
||||
ASSERT_EQ(totalQbinBytes, Header + ps.size() * Descriptor + payloadLength);
|
||||
|
||||
auto r = particle::ingress::QbinV2Decoder::decode(meta(), b);
|
||||
EXPECT_TRUE(r.accepted()) << r.detail;
|
||||
}
|
||||
TEST(ParticleQbinV2Decoder, RejectsPlaneCountAndDescriptorEnums) { auto b=fixture();u16(b,12,0);recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidHeader); b=fixture();u16(b,12,33);recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidHeader); b=fixture();b[114]=0;recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidDescriptor); b=fixture();b[140]=4;recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidDescriptor); b=fixture();b[141]=4;recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidDescriptor); }
|
||||
TEST(ParticleQbinV2Decoder, RejectsDescriptorMetadataAndNumericParameters) { auto b=fixture();u16(b,142,1);recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidDescriptor); b=fixture();b[115]=2;recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidDescriptor); b=fixture();u32(b,124,3);recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidDescriptor); b=fixture();f32(b,116,0);recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidDescriptor); b=fixture();f32(b,116,std::numeric_limits<float>::infinity());recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidDescriptor); b=fixture();f32(b,120,std::numeric_limits<float>::quiet_NaN());recalc(b);EXPECT_EQ(decodeCode(b),Code::InvalidDescriptor); }
|
||||
TEST(ParticleQbinV2Decoder, EnforcesBitsetAndValidityPairing) { auto ps=basePlanes();ps[0].type=6;ps[0].raw={15};auto b=fixture(2,2,ps);EXPECT_EQ(decodeCode(b),Code::InvalidValidity); ps=basePlanes();ps[2].type=3;ps[2].raw={0,0,0,0};b=fixture(2,2,ps);EXPECT_EQ(decodeCode(b),Code::InvalidValidity); }
|
||||
|
||||
@@ -729,3 +729,8 @@ Android V3-08 单次综合验收已完成并关闭。Native `13.4.1-particle.2`
|
||||
- Header width 和 descriptor count 的 big/mixed-endian corruption 均在重算 CRC 后 fail-closed,分别结构化为 `LimitExceeded`、`InvalidDescriptor`。
|
||||
- 1447×1449、7 plane 的 raw sum=31,712,633 bytes,canonical payload=31,712,648 bytes,15 bytes padding 不计入 32 MiB decoded raw limit 且 decoder Accepted。
|
||||
- Linux runner 重建/重链、STEP-074 24/24、STEP-073 11/11、既有 V3 11/11 与 `git diff --check` 均 PASS;未改 production Decoder、Host、网络、JNI、Android/RN、Binding/Projection、Renderer 或 iOS/Metal。
|
||||
|
||||
### 2026-09-13 STEP-074 v4 审计最终修正
|
||||
|
||||
- `AcceptsRawLimitWithCanonicalPaddingExcluded` 改为 1101×1890(2,080,890 cells)的 17-plane canonical fixture:single shared validity BITSET 加 16 个 UINT8 numeric plane。rawSum=33,554,352 bytes,小于 32 MiB limit=33,554,432;payloadLength=33,554,448 bytes,大于 limit 与 rawSum;totalQbinBytes=33,555,104 bytes,小于 64 MiB。
|
||||
- production `QbinV2Decoder::decode(...)` Accepted;未发现生产缺陷,未改 Decoder 或 Host/网络/JNI/RN/Binding/Projection/Renderer。真实 runner 重建 PASS,Decoder/Ingress 24/24、Runtime/Profile 11/11、Source 回归 11/11 PASS,`git diff --check` PASS;未执行 Android Gradle/APK/ADB/Jest,按范围停止。
|
||||
|
||||
Reference in New Issue
Block a user