Project: libdwarf-code (davea42/libdwarf-code), language: c++
Vulnerability instance: libdwarf.cve-2022-34299
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/davea42/libdwarf-code/issues/119
## Description:
Issue: davea42/libdwarf-code#119
Title: heap overflow in dwarf_global_formref_b
State: closed
Created by: sleicasper
Created at: 2022-06-15 12:36:15+00:00

Issue Body:

asan output:
```
=================================================================
==3946410==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61b000000697 at pc 0x0000005d9f2d bp 0x7fffffff94f0 sp 0x7fffffff94e8
READ of size 8 at 0x61b000000697 thread T0
    #0 0x5d9f2c in dwarf_global_formref_b /libdwarf/SRC/src/lib/libdwarf/dwarf_form.c:840:9
    #1 0x5d87b4 in dwarf_global_formref /libdwarf/SRC/src/lib/libdwarf/dwarf_form.c:671:11
    #2 0x54c86e in dd_get_integer_and_name /libdwarf/SRC/src/bin/dwarfdump/print_die.c:2400:20
    #3 0x546d08 in print_attribute /libdwarf/SRC/src/bin/dwarfdump/print_die.c:3981:15
    #4 0x54464a in print_one_die /libdwarf/SRC/src/bin/dwarfdump/print_die.c:2290:25
    #5 0x55a11d in print_die_and_children_internal /libdwarf/SRC/src/bin/dwarfdump/print_die.c:1632:21
    #6 0x540f23 in print_die_and_children /libdwarf/SRC/src/bin/dwarfdump/print_die.c:954:11
    #7 0x540f23 in print_one_die_section /libdwarf/SRC/src/bin/dwarfdump/print_die.c:1283:28
    #8 0x540f23 in print_infos /libdwarf/SRC/src/bin/dwarfdump/print_die.c:648:12
    #9 0x50b925 in process_one_file /libdwarf/SRC/src/bin/dwarfdump/dwarfdump.c:1001:15
    #10 0x5099ec in main /libdwarf/SRC/src/bin/dwarfdump/dwarfdump.c:503:9
    #11 0x7ffff7bfb082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
    #12 0x42848d in _start (/libdwarf/fuzzrun/dwarfdump+0x42848d)

0x61b000000697 is located 5 bytes to the right of 1554-byte region [0x61b000000080,0x61b000000692)
allocated by thread T0 here:
    #0 0x4cd59f in malloc /fuzz/fuzzdeps/llvm-project-11.0.0/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
    #1 0x6a3554 in elf_load_nolibelf_section /libdwarf/SRC/src/lib/libdwarf/dwarf_elfread.c:229:26

SUMMARY: AddressSanitizer: heap-buffer-overflow /libdwarf/SRC/src/lib/libdwarf/dwarf_form.c:840:9 in dwarf_global_formref_b
Shadow bytes around the buggy address:
  0x0c367fff8080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c367fff8090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c367fff80a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c367fff80b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c367fff80c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c367fff80d0: 00 00[02]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c367fff80e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c367fff80f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c367fff8100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c367fff8110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c367fff8120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==3946410==ABORTING
```
poc:
[poc.zip](https://github.com/davea42/libdwarf-code/files/8909309/poc.zip)


repro:
```
dwarfdump -vv -a ./poc
```



Comments:
Comment by davea42 on 2022-06-16 00:08:41+00:00:
The bug was code failing to check if reading a DW_FORM_ref_sig8 would
run off the end of the section being read. 
This was a long-standing bug introduced with DWARF4 support.
Given dwarf vulnerability  id: DW202206-001
The fix committed moments ago.

Attachments:
https://github.com/davea42/libdwarf-code/files/8909309/poc.zip

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
export CFLAGS="${CFLAGS} -g -Werror"
export CXXFLAGS="${CXXFLAGS} -g -Werror"
mkdir -p build
cd build
cmake ../
make -j$(nproc)
mkdir -p $SRC/corp

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool
RUN git clone https://github.com/davea42/libdwarf-code libdwarf-code
RUN git -C libdwarf-code checkout bc068ac4049261bcd5cc6293aa2c90dc58fbcf8d
WORKDIR $SRC/libdwarf-code
COPY build.sh $SRC/

Additional files:
filename: fuzz_init_binary.c
content: /* Copyright 2021 Google LLC
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.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/*
 * Libdwarf library callers can only use these headers.
 */
#include "dwarf.h"
#include "libdwarf.h"

/*
 * A fuzzer that simulates a small part of the simplereader.c example.
 * This fuzzer targets dwarf_init_b.
 */
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  char filename[256];
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());

  FILE *fp = fopen(filename, "wb");
  if (!fp) {
    return 0;
  }
  fwrite(data, size, 1, fp);
  fclose(fp);

  int my_init_fd = 0;
  Dwarf_Ptr errarg = 0;
  Dwarf_Handler errhand = 0;
  Dwarf_Error *errp = NULL;
  Dwarf_Debug dbg = 0;

  my_init_fd = open(filename, O_RDONLY);
  if (my_init_fd != -1) {
    dwarf_init_b(my_init_fd,DW_GROUPNUMBER_ANY,errhand,errarg,&dbg,errp);
    dwarf_finish(dbg);
    close(my_init_fd);
  }

  unlink(filename);
  return 0;
}

filename: fuzz_init_path.c
content: /* Copyright 2021 Google LLC
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.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

/*
 * Libdwarf library callers can only use these headers.
 */
#include "dwarf.h"
#include "libdwarf.h"

/*
 * A fuzzer that simulates a small part of the simplereader.c example.
 */
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  char filename[256];
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());

  FILE *fp = fopen(filename, "wb");
  if (!fp) {
    return 0;
  }
  fwrite(data, size, 1, fp);
  fclose(fp);
  Dwarf_Ptr errarg = 0;
  Dwarf_Handler errhand = 0;
  Dwarf_Debug dbg = 0;
  Dwarf_Error *errp = NULL;
#define MACHO_PATH_LEN 2000
  char macho_real_path[2000];
  dwarf_init_path(filename, macho_real_path, MACHO_PATH_LEN,
                  DW_GROUPNUMBER_ANY, errhand, errarg, &dbg, errp);

  dwarf_finish(dbg);

  unlink(filename);
  return 0;
}