Skip to content

Loss of coverage (#2) #4

@vanhauser-thc

Description

@vanhauser-thc

This is an extension to issue #2 - I found out where the loss of coverage is.
There seems to be a logic bug that sometimes results in a basic block not being instrumented when it should.

In the following example the if (argc < 2) { BASIC_BLOCK } basic block is not instrumented.
Note that is has to be compiled with AFL_DONT_OPTIMIZE:
AFL_DONT_OPTIMIZE=1 MARKSET=1 afl-clang-fast -o bug bug.c

#include <stdio.h>
#include <stdlib.h>

void foo(int a) {
  printf("foo\n");
  if (a == 1)
    printf("1\n");
  else
    printf("2\n");
  printf("done\n");
}

void bar() {
  printf("bar\n");
}

int main(int argc, char *argv[]) {
  printf("main\n");
  if (argc < 2) {
    printf("argc<2\n"); // *This is not instrumented*
    return -1;
  } else if (argc > 2)
    printf("argc>2\n");
  else
    printf("argc=2\n");
  printf("ok\n");
  if (argv[1][0] == 'a')
    foo(atoi(argv[1]));
  else
    bar();
  printf("end\n");
  return 0;
}

The disassembly looks like this:

Dump of assembler code for function main:
   0x0000000000401320 <+0>:	push   rbp
   0x0000000000401321 <+1>:	mov    rbp,rsp
   0x0000000000401324 <+4>:	sub    rsp,0x20
   0x0000000000401328 <+8>:	mov    DWORD PTR [rbp-0x4],0x0
   0x000000000040132f <+15>:	mov    DWORD PTR [rbp-0x8],edi
   0x0000000000401332 <+18>:	mov    QWORD PTR [rbp-0x10],rsi
   0x0000000000401336 <+22>:	movabs rdi,0x402017
   0x0000000000401340 <+32>:	mov    al,0x0
   0x0000000000401342 <+34>:	call   0x401080 <printf@plt>
   0x0000000000401347 <+39>:	cmp    DWORD PTR [rbp-0x8],0x2
   0x000000000040134b <+43>:	jge    0x40136e <main+78>
-> HERE begins the non-instrumented basic block
   0x0000000000401351 <+49>:	movabs rdi,0x40201d
   0x000000000040135b <+59>:	mov    al,0x0
   0x000000000040135d <+61>:	call   0x401080 <printf@plt>
   0x0000000000401362 <+66>:	mov    DWORD PTR [rbp-0x4],0xffffffff
   0x0000000000401369 <+73>:	jmp    0x401482 <main+354>
-> HERE it jumps to the end

Decompiled in Ghidra it looks like this:

int main(uint param_1,char** param_2) {
 // remove variable declarations
  printf("main\n");
  if ((int)param_1 < 2) {
    printf("argc<2\n");
    local_c = 0xffffffff;
  } else {
    ...
  }
 return (ulong)local_c;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions