fix(asm): bound the data section to what the image can materialise
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
dd074dbafd
commit
7878112b93
2 files changed
+24
-7
No files matched your search
@@ -82,7 +82,9 @@ func FuzzAssembleAMD64(f *testing.F) {
|
||||
// above never reach.
|
||||
f.Add("TEXT ·f(SB), $0\n\tBOGUSINSTR AX, BX\n\tRET\n")
|
||||
f.Add("GLOBL d(SB), $-8\n")
|
||||
f.Add("GLOBL d(SB), $-1\n")
|
||||
f.Add("GLOBL d(SB), $0x7FFFFFFFFFFFFFFF\n")
|
||||
f.Add("GLOBL d(SB), $0x4000000\nDATA e+0(SB)/8, $1\nGLOBL e(SB), $0x4000000\nDATA f+0(SB)/8, $1\nGLOBL f(SB), $0x4000000\n")
|
||||
f.Add("DATA d+0(SB)/9, $1\nGLOBL d(SB), $8\n")
|
||||
f.Add("TEXT ·f(SB), NOSPLIT, $0\n\tADJSP $16\n\tRET\n")
|
||||
f.Add("#define A A\nA\n")
|
||||
|
||||
+22
-7
@@ -607,13 +607,20 @@ func checkDuplicateDecls(f *ast.File) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// maxSymbolSize is the ceiling on one GLOBL's declared size. The image
|
||||
// materialises the symbol's bytes at assembly time, where the toolchain
|
||||
// defers the cost to its linker, so the bound is the toolchain's own: obj
|
||||
// rejects anything over 2,000,000,000 bytes as "symbol too large", and a
|
||||
// negative size, which the toolchain's int64 field tolerates and its linker
|
||||
// refuses, is diagnosed here rather than attempted.
|
||||
const maxSymbolSize = 2_000_000_000
|
||||
// The data section's size ceilings. The image materialises every GLOBL's
|
||||
// bytes at assembly time, where the toolchain defers the cost to its linker,
|
||||
// so gasm needs its own bound and a diagnostic in place of an allocation
|
||||
// failure. The toolchain's own limit (obj's "symbol too large", 2,000,000,000
|
||||
// bytes) would let a twenty-five byte input demand four gigabytes of resident
|
||||
// memory (measured: `GLOBL d(SB), $2000000000` peaks at 3.92 GiB RSS), which
|
||||
// starves the memory fence the test recipes run under when the fuzz workers
|
||||
// share it. 64 MiB per symbol and 128 MiB per file sit two orders above any
|
||||
// real assembly symbol (the runtime's largest GLOBL is KiB-scale) and keep a
|
||||
// worker's worst-case peak near its fence share.
|
||||
const (
|
||||
maxSymbolSize = 64 << 20
|
||||
maxDataSize = 128 << 20
|
||||
)
|
||||
|
||||
// collectData gathers the file's static symbols (GLOBL) and their initial
|
||||
// contents (DATA) into byte buffers. Two passes: the Plan 9 convention puts
|
||||
@@ -627,6 +634,7 @@ func collectData(f *ast.File) ([]dataSym, error) {
|
||||
}
|
||||
index := map[string]int{}
|
||||
var syms []dataSym
|
||||
total := 0
|
||||
for _, d := range f.Decls {
|
||||
gd, ok := d.(*ast.Globl)
|
||||
if !ok {
|
||||
@@ -639,9 +647,16 @@ func collectData(f *ast.File) ([]dataSym, error) {
|
||||
size := 0
|
||||
if gd.Size != nil && gd.Size.Imm.HasVal {
|
||||
size = int(gd.Size.Imm.Val)
|
||||
if gd.Size.Imm.Neg {
|
||||
size = -size
|
||||
}
|
||||
if size < 0 || size > maxSymbolSize {
|
||||
return nil, fmt.Errorf("GLOBL %q: symbol too large (%d bytes > %d bytes)", name, size, maxSymbolSize)
|
||||
}
|
||||
if total+size > maxDataSize {
|
||||
return nil, fmt.Errorf("GLOBL %q: data section too large (%d bytes > %d bytes)", name, total+size, maxDataSize)
|
||||
}
|
||||
total += size
|
||||
}
|
||||
index[name] = len(syms)
|
||||
ds := dataSym{
|
||||
|
||||
Reference in new issue
Block a user