// Copyright 2022 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package elf import ( "bytes" "debug/elf" "encoding/binary" "reflect" "testing" ) func Test_elfIdentifierFromReaderAt_BadElfFile(t *testing.T) { tests := []struct { name string contents string }{ { name: "empty", contents: "", }, { name: "text", contents: "#!/bin/bash\necho foobar", }, { name: "empty elf", contents: emptyElfFile(), }, { name: "short section header", contents: shortSectionHeaderElfFile(), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { buf := bytes.NewReader([]byte(tt.contents)) _, err := elfIdentifierFromReaderAt(buf, "<>", false) if err == nil { t.Errorf("expected error reading bad elf file without allowMissing") } _, err = elfIdentifierFromReaderAt(buf, "<>", true) if err != nil { t.Errorf("expected no error reading bad elf file with allowMissing, got %q", err.Error()) } }) } } func Test_readNote(t *testing.T) { note := []byte{ 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x4e, 0x55, 0x00, 0xca, 0xaf, 0x44, 0xd2, 0x82, 0x78, 0x68, 0xfe, 0xc0, 0x90, 0xa3, 0x43, 0x85, 0x36, 0x6c, 0xc7, } descs, err := readNote(bytes.NewBuffer(note), binary.LittleEndian) if err != nil { t.Fatalf("unexpected error in readNote: %s", err) } expectedDescs := map[string][]byte{ "GNU\x00": []byte{0xca, 0xaf, 0x44, 0xd2, 0x82, 0x78, 0x68, 0xfe, 0xc0, 0x90, 0xa3, 0x43, 0x85, 0x36, 0x6c, 0xc7}, } if !reflect.DeepEqual(descs, expectedDescs) { t.Errorf("incorrect return, want %#v got %#v", expectedDescs, descs) } } // emptyElfFile returns an elf file header with no program headers or sections. func emptyElfFile() string { ident := [elf.EI_NIDENT]byte{} identBuf := bytes.NewBuffer(ident[0:0:elf.EI_NIDENT]) binary.Write(identBuf, binary.LittleEndian, []byte("\x7fELF")) binary.Write(identBuf, binary.LittleEndian, elf.ELFCLASS64) binary.Write(identBuf, binary.LittleEndian, elf.ELFDATA2LSB) binary.Write(identBuf, binary.LittleEndian, elf.EV_CURRENT) binary.Write(identBuf, binary.LittleEndian, elf.ELFOSABI_LINUX) binary.Write(identBuf, binary.LittleEndian, make([]byte, 8)) header := elf.Header64{ Ident: ident, Type: uint16(elf.ET_EXEC), Machine: uint16(elf.EM_X86_64), Version: uint32(elf.EV_CURRENT), Entry: 0, Phoff: uint64(binary.Size(elf.Header64{})), Shoff: uint64(binary.Size(elf.Header64{})), Flags: 0, Ehsize: uint16(binary.Size(elf.Header64{})), Phentsize: 0x38, Phnum: 0, Shentsize: 0x40, Shnum: 0, Shstrndx: 0, } buf := &bytes.Buffer{} binary.Write(buf, binary.LittleEndian, header) return buf.String() } // shortSectionHeader returns an elf file header with a section header that extends past the end of // the file. func shortSectionHeaderElfFile() string { ident := [elf.EI_NIDENT]byte{} identBuf := bytes.NewBuffer(ident[0:0:elf.EI_NIDENT]) binary.Write(identBuf, binary.LittleEndian, []byte("\x7fELF")) binary.Write(identBuf, binary.LittleEndian, elf.ELFCLASS64) binary.Write(identBuf, binary.LittleEndian, elf.ELFDATA2LSB) binary.Write(identBuf, binary.LittleEndian, elf.EV_CURRENT) binary.Write(identBuf, binary.LittleEndian, elf.ELFOSABI_LINUX) binary.Write(identBuf, binary.LittleEndian, make([]byte, 8)) header := elf.Header64{ Ident: ident, Type: uint16(elf.ET_EXEC), Machine: uint16(elf.EM_X86_64), Version: uint32(elf.EV_CURRENT), Entry: 0, Phoff: uint64(binary.Size(elf.Header64{})), Shoff: uint64(binary.Size(elf.Header64{})), Flags: 0, Ehsize: uint16(binary.Size(elf.Header64{})), Phentsize: 0x38, Phnum: 0, Shentsize: 0x40, Shnum: 1, Shstrndx: 0, } buf := &bytes.Buffer{} binary.Write(buf, binary.LittleEndian, header) binary.Write(buf, binary.LittleEndian, []byte{0}) return buf.String() }