1// Copyright 2022 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package elf 16 17import ( 18 "bytes" 19 "debug/elf" 20 "encoding/binary" 21 "reflect" 22 "testing" 23) 24 25func Test_elfIdentifierFromReaderAt_BadElfFile(t *testing.T) { 26 tests := []struct { 27 name string 28 contents string 29 }{ 30 { 31 name: "empty", 32 contents: "", 33 }, 34 { 35 name: "text", 36 contents: "#!/bin/bash\necho foobar", 37 }, 38 { 39 name: "empty elf", 40 contents: emptyElfFile(), 41 }, 42 { 43 name: "short section header", 44 contents: shortSectionHeaderElfFile(), 45 }, 46 } 47 48 for _, tt := range tests { 49 t.Run(tt.name, func(t *testing.T) { 50 buf := bytes.NewReader([]byte(tt.contents)) 51 _, err := elfIdentifierFromReaderAt(buf, "<>", false) 52 if err == nil { 53 t.Errorf("expected error reading bad elf file without allowMissing") 54 } 55 _, err = elfIdentifierFromReaderAt(buf, "<>", true) 56 if err != nil { 57 t.Errorf("expected no error reading bad elf file with allowMissing, got %q", err.Error()) 58 } 59 }) 60 } 61} 62 63func Test_readNote(t *testing.T) { 64 note := []byte{ 65 0x04, 0x00, 0x00, 0x00, 66 0x10, 0x00, 0x00, 0x00, 67 0x03, 0x00, 0x00, 0x00, 68 0x47, 0x4e, 0x55, 0x00, 69 0xca, 0xaf, 0x44, 0xd2, 0x82, 0x78, 0x68, 0xfe, 0xc0, 0x90, 0xa3, 0x43, 0x85, 0x36, 0x6c, 0xc7, 70 } 71 72 descs, err := readNote(bytes.NewBuffer(note), binary.LittleEndian) 73 if err != nil { 74 t.Fatalf("unexpected error in readNote: %s", err) 75 } 76 77 expectedDescs := map[string][]byte{ 78 "GNU\x00": []byte{0xca, 0xaf, 0x44, 0xd2, 0x82, 0x78, 0x68, 0xfe, 0xc0, 0x90, 0xa3, 0x43, 0x85, 0x36, 0x6c, 0xc7}, 79 } 80 81 if !reflect.DeepEqual(descs, expectedDescs) { 82 t.Errorf("incorrect return, want %#v got %#v", expectedDescs, descs) 83 } 84} 85 86// emptyElfFile returns an elf file header with no program headers or sections. 87func emptyElfFile() string { 88 ident := [elf.EI_NIDENT]byte{} 89 identBuf := bytes.NewBuffer(ident[0:0:elf.EI_NIDENT]) 90 binary.Write(identBuf, binary.LittleEndian, []byte("\x7fELF")) 91 binary.Write(identBuf, binary.LittleEndian, elf.ELFCLASS64) 92 binary.Write(identBuf, binary.LittleEndian, elf.ELFDATA2LSB) 93 binary.Write(identBuf, binary.LittleEndian, elf.EV_CURRENT) 94 binary.Write(identBuf, binary.LittleEndian, elf.ELFOSABI_LINUX) 95 binary.Write(identBuf, binary.LittleEndian, make([]byte, 8)) 96 97 header := elf.Header64{ 98 Ident: ident, 99 Type: uint16(elf.ET_EXEC), 100 Machine: uint16(elf.EM_X86_64), 101 Version: uint32(elf.EV_CURRENT), 102 Entry: 0, 103 Phoff: uint64(binary.Size(elf.Header64{})), 104 Shoff: uint64(binary.Size(elf.Header64{})), 105 Flags: 0, 106 Ehsize: uint16(binary.Size(elf.Header64{})), 107 Phentsize: 0x38, 108 Phnum: 0, 109 Shentsize: 0x40, 110 Shnum: 0, 111 Shstrndx: 0, 112 } 113 114 buf := &bytes.Buffer{} 115 binary.Write(buf, binary.LittleEndian, header) 116 return buf.String() 117} 118 119// shortSectionHeader returns an elf file header with a section header that extends past the end of 120// the file. 121func shortSectionHeaderElfFile() string { 122 ident := [elf.EI_NIDENT]byte{} 123 identBuf := bytes.NewBuffer(ident[0:0:elf.EI_NIDENT]) 124 binary.Write(identBuf, binary.LittleEndian, []byte("\x7fELF")) 125 binary.Write(identBuf, binary.LittleEndian, elf.ELFCLASS64) 126 binary.Write(identBuf, binary.LittleEndian, elf.ELFDATA2LSB) 127 binary.Write(identBuf, binary.LittleEndian, elf.EV_CURRENT) 128 binary.Write(identBuf, binary.LittleEndian, elf.ELFOSABI_LINUX) 129 binary.Write(identBuf, binary.LittleEndian, make([]byte, 8)) 130 131 header := elf.Header64{ 132 Ident: ident, 133 Type: uint16(elf.ET_EXEC), 134 Machine: uint16(elf.EM_X86_64), 135 Version: uint32(elf.EV_CURRENT), 136 Entry: 0, 137 Phoff: uint64(binary.Size(elf.Header64{})), 138 Shoff: uint64(binary.Size(elf.Header64{})), 139 Flags: 0, 140 Ehsize: uint16(binary.Size(elf.Header64{})), 141 Phentsize: 0x38, 142 Phnum: 0, 143 Shentsize: 0x40, 144 Shnum: 1, 145 Shstrndx: 0, 146 } 147 148 buf := &bytes.Buffer{} 149 binary.Write(buf, binary.LittleEndian, header) 150 binary.Write(buf, binary.LittleEndian, []byte{0}) 151 return buf.String() 152} 153