if _, err := r.ReadAt(dat, offset); err != nil {
return nil, err
}
- f.Loads = make([]Load, f.Ncmd)
+ c := saferio.SliceCap([]Load{}, uint64(f.Ncmd))
+ if c < 0 {
+ return nil, &FormatError{offset, "too many load commands", nil}
+ }
+ f.Loads = make([]Load, 0, c)
bo := f.ByteOrder
- for i := range f.Loads {
+ for i := uint32(0); i < f.Ncmd; i++ {
// Each load command begins with uint32 command and length.
if len(dat) < 8 {
return nil, &FormatError{offset, "command block too small", nil}
var s *Segment
switch cmd {
default:
- f.Loads[i] = LoadBytes(cmddat)
+ f.Loads = append(f.Loads, LoadBytes(cmddat))
case LoadCmdRpath:
var hdr RpathCmd
}
l.Path = cstring(cmddat[hdr.Path:])
l.LoadBytes = LoadBytes(cmddat)
- f.Loads[i] = l
+ f.Loads = append(f.Loads, l)
case LoadCmdDylib:
var hdr DylibCmd
l.CurrentVersion = hdr.CurrentVersion
l.CompatVersion = hdr.CompatVersion
l.LoadBytes = LoadBytes(cmddat)
- f.Loads[i] = l
+ f.Loads = append(f.Loads, l)
case LoadCmdSymtab:
var hdr SymtabCmd
} else {
symsz = 12
}
- symdat := make([]byte, int(hdr.Nsyms)*symsz)
- if _, err := r.ReadAt(symdat, int64(hdr.Symoff)); err != nil {
+ symdat, err := saferio.ReadDataAt(r, uint64(hdr.Nsyms)*uint64(symsz), int64(hdr.Symoff))
+ if err != nil {
return nil, err
}
st, err := f.parseSymtab(symdat, strtab, cmddat, &hdr, offset)
if err != nil {
return nil, err
}
- f.Loads[i] = st
+ f.Loads = append(f.Loads, st)
f.Symtab = st
case LoadCmdDysymtab:
st.LoadBytes = LoadBytes(cmddat)
st.DysymtabCmd = hdr
st.IndirectSyms = x
- f.Loads[i] = st
+ f.Loads = append(f.Loads, st)
f.Dysymtab = st
case LoadCmdSegment:
s.Prot = seg32.Prot
s.Nsect = seg32.Nsect
s.Flag = seg32.Flag
- f.Loads[i] = s
+ f.Loads = append(f.Loads, s)
for i := 0; i < int(s.Nsect); i++ {
var sh32 Section32
if err := binary.Read(b, bo, &sh32); err != nil {
s.Prot = seg64.Prot
s.Nsect = seg64.Nsect
s.Flag = seg64.Flag
- f.Loads[i] = s
+ f.Loads = append(f.Loads, s)
for i := 0; i < int(s.Nsect); i++ {
var sh64 Section64
if err := binary.Read(b, bo, &sh64); err != nil {
}
}
if s != nil {
+ if int64(s.Offset) < 0 {
+ return nil, &FormatError{offset, "invalid section offset", s.Offset}
+ }
+ if int64(s.Filesz) < 0 {
+ return nil, &FormatError{offset, "invalid section file size", s.Filesz}
+ }
s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Filesz))
s.ReaderAt = s.sr
}
func (f *File) parseSymtab(symdat, strtab, cmddat []byte, hdr *SymtabCmd, offset int64) (*Symtab, error) {
bo := f.ByteOrder
- symtab := make([]Symbol, hdr.Nsyms)
+ c := saferio.SliceCap([]Symbol{}, uint64(hdr.Nsyms))
+ if c < 0 {
+ return nil, &FormatError{offset, "too many symbols", nil}
+ }
+ symtab := make([]Symbol, 0, c)
b := bytes.NewReader(symdat)
- for i := range symtab {
+ for i := 0; i < int(hdr.Nsyms); i++ {
var n Nlist64
if f.Magic == Magic64 {
if err := binary.Read(b, bo, &n); err != nil {
n.Desc = n32.Desc
n.Value = uint64(n32.Value)
}
- sym := &symtab[i]
if n.Name >= uint32(len(strtab)) {
return nil, &FormatError{offset, "invalid name in symbol table", n.Name}
}
if strings.Contains(name, ".") && name[0] == '_' {
name = name[1:]
}
- sym.Name = name
- sym.Type = n.Type
- sym.Sect = n.Sect
- sym.Desc = n.Desc
- sym.Value = n.Value
+ symtab = append(symtab, Symbol{
+ Name: name,
+ Type: n.Type,
+ Sect: n.Sect,
+ Desc: n.Desc,
+ Value: n.Value,
+ })
}
st := new(Symtab)
st.LoadBytes = LoadBytes(cmddat)
sh.ReaderAt = sh.sr
if sh.Nreloc > 0 {
- reldat := make([]byte, int(sh.Nreloc)*8)
- if _, err := r.ReadAt(reldat, int64(sh.Reloff)); err != nil {
+ reldat, err := saferio.ReadDataAt(r, uint64(sh.Nreloc)*8, int64(sh.Reloff))
+ if err != nil {
return err
}
b := bytes.NewReader(reldat)