package fog import ( "archive/zip" "bytes" "compress/zlib" "strings" "testing" ) // TestZlibDecompressRejectsBomb 守住「zlib 流能解出任意长度」这个口子。 // 几十 MB 的全零数据压出来只有几十 KB,解压时不设上限就是一个标准 zip bomb—— // 上传接口只有站长能用,但 1C1G 的机器被打爆一次就够受。 func TestZlibDecompressRejectsBomb(t *testing.T) { var buf bytes.Buffer zw := zlib.NewWriter(&buf) zeros := make([]byte, 1<<20) written := 0 for written <= maxTileZBytes { if _, err := zw.Write(zeros); err != nil { t.Fatal(err) } written += len(zeros) } if err := zw.Close(); err != nil { t.Fatal(err) } t.Logf("构造出 %d 字节的 zlib 流,解压后 %d 字节", buf.Len(), written) if _, err := zlibDecompress(buf.Bytes()); err == nil { t.Errorf("解压出 %d 字节(上限 %d)的流应当被拒绝", written, maxTileZBytes) } else { t.Logf("已拒绝: %v", err) } } // TestZlibDecompressNormalStream 反向确认:正常大小的流仍能原样解出, // 免得上面那条把限额做得太紧、把真快照也一起挡了。 func TestZlibDecompressNormalStream(t *testing.T) { var buf bytes.Buffer zw := zlib.NewWriter(&buf) want := strings.Repeat("rond", 4096) if _, err := zw.Write([]byte(want)); err != nil { t.Fatal(err) } zw.Close() got, err := zlibDecompress(buf.Bytes()) if err != nil { t.Fatalf("正常流不该被拒: %v", err) } if string(got) != want { t.Errorf("解压结果不一致: %d 字节 → %d 字节", len(want), len(got)) } } // TestDecodeRejectsOversizedTileEntry 确认 Decode 这一层也限住了「压缩后」的体积: // 条目本身就超限时直接报错,而不是先整个读进内存再判断。 func TestDecodeRejectsOversizedTileEntry(t *testing.T) { var buf bytes.Buffer zw := zip.NewWriter(&buf) w, err := zw.Create("Model/*/" + tileName(42)) if err != nil { t.Fatal(err) } if _, err := w.Write([]byte(strings.Repeat("x", maxTileRawBytes+1))); err != nil { t.Fatal(err) } if err := zw.Close(); err != nil { t.Fatal(err) } if _, _, err := Decode(buf.Bytes()); err == nil { t.Errorf("压缩后超过 %d 字节的瓦片应当被拒绝", maxTileRawBytes) } else { t.Logf("已拒绝: %v", err) } }