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.
|
// above never reach.
|
||||||
f.Add("TEXT ·f(SB), $0\n\tBOGUSINSTR AX, BX\n\tRET\n")
|
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), $-8\n")
|
||||||
|
f.Add("GLOBL d(SB), $-1\n")
|
||||||
f.Add("GLOBL d(SB), $0x7FFFFFFFFFFFFFFF\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("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("TEXT ·f(SB), NOSPLIT, $0\n\tADJSP $16\n\tRET\n")
|
||||||
f.Add("#define A A\nA\n")
|
f.Add("#define A A\nA\n")
|
||||||
|
|||||||
+22
-7
@@ -607,13 +607,20 @@ func checkDuplicateDecls(f *ast.File) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// maxSymbolSize is the ceiling on one GLOBL's declared size. The image
|
// The data section's size ceilings. The image materialises every GLOBL's
|
||||||
// materialises the symbol's bytes at assembly time, where the toolchain
|
// bytes at assembly time, where the toolchain defers the cost to its linker,
|
||||||
// defers the cost to its linker, so the bound is the toolchain's own: obj
|
// so gasm needs its own bound and a diagnostic in place of an allocation
|
||||||
// rejects anything over 2,000,000,000 bytes as "symbol too large", and a
|
// failure. The toolchain's own limit (obj's "symbol too large", 2,000,000,000
|
||||||
// negative size, which the toolchain's int64 field tolerates and its linker
|
// bytes) would let a twenty-five byte input demand four gigabytes of resident
|
||||||
// refuses, is diagnosed here rather than attempted.
|
// memory (measured: `GLOBL d(SB), $2000000000` peaks at 3.92 GiB RSS), which
|
||||||
const maxSymbolSize = 2_000_000_000
|
// 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
|
// collectData gathers the file's static symbols (GLOBL) and their initial
|
||||||
// contents (DATA) into byte buffers. Two passes: the Plan 9 convention puts
|
// 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{}
|
index := map[string]int{}
|
||||||
var syms []dataSym
|
var syms []dataSym
|
||||||
|
total := 0
|
||||||
for _, d := range f.Decls {
|
for _, d := range f.Decls {
|
||||||
gd, ok := d.(*ast.Globl)
|
gd, ok := d.(*ast.Globl)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -639,9 +647,16 @@ func collectData(f *ast.File) ([]dataSym, error) {
|
|||||||
size := 0
|
size := 0
|
||||||
if gd.Size != nil && gd.Size.Imm.HasVal {
|
if gd.Size != nil && gd.Size.Imm.HasVal {
|
||||||
size = int(gd.Size.Imm.Val)
|
size = int(gd.Size.Imm.Val)
|
||||||
|
if gd.Size.Imm.Neg {
|
||||||
|
size = -size
|
||||||
|
}
|
||||||
if size < 0 || size > maxSymbolSize {
|
if size < 0 || size > maxSymbolSize {
|
||||||
return nil, fmt.Errorf("GLOBL %q: symbol too large (%d bytes > %d bytes)", name, 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)
|
index[name] = len(syms)
|
||||||
ds := dataSym{
|
ds := dataSym{
|
||||||
|
|||||||
Reference in new issue
Block a user