Use chunked ISO search instead of reading entire 1.2GB file into memory
build-and-push / test (push) Successful in 39s
build-and-push / build-and-push (push) Successful in 1m15s

os.ReadFile on the ISO was OOM-killing the container. Switch to 8MB
chunked reads with overlap to handle matches spanning chunk boundaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-14 17:16:53 -04:00
parent fa570b1571
commit 8b3b2e874a
+42 -10
View File
@@ -170,13 +170,16 @@ func rewriteGrubConfig(original, answerURL string) string {
return strings.Join(collapsed, "\n")
}
// findAllOccurrences searches the entire ISO file for all locations where
// the grub.cfg content appears — this catches both the ISO9660 filesystem
// copy and any copy inside an embedded EFI boot partition image.
func findAllOccurrences(isoPath string, content []byte) ([]int64, error) {
data, err := os.ReadFile(isoPath)
f, err := os.Open(isoPath)
if err != nil {
return nil, fmt.Errorf("read ISO: %w", err)
return nil, fmt.Errorf("open ISO: %w", err)
}
defer f.Close()
stat, err := f.Stat()
if err != nil {
return nil, err
}
needle := content
@@ -184,20 +187,49 @@ func findAllOccurrences(isoPath string, content []byte) ([]int64, error) {
needle = needle[:256]
}
const chunkSize = 8 * 1024 * 1024
overlap := len(needle) - 1
buf := make([]byte, chunkSize+overlap)
var offsets []int64
start := 0
filePos := int64(0)
for filePos < stat.Size() {
readStart := filePos
if filePos > 0 {
readStart -= int64(overlap)
}
n, err := f.ReadAt(buf, readStart)
if n == 0 {
break
}
searchFrom := 0
if filePos > 0 {
searchFrom = overlap
}
chunk := buf[:n]
pos := searchFrom
for {
idx := bytes.Index(data[start:], needle)
idx := bytes.Index(chunk[pos:], needle)
if idx == -1 {
break
}
offsets = append(offsets, int64(start+idx))
start += idx + 1
offsets = append(offsets, readStart+int64(pos)+int64(idx))
pos += idx + 1
}
filePos += chunkSize
if err != nil {
break
}
}
if len(offsets) == 0 {
return nil, fmt.Errorf("grub.cfg content not found in ISO raw data (searched %d bytes with %d-byte needle)",
len(data), len(needle))
stat.Size(), len(needle))
}
return offsets, nil