On Mon, Nov 24, 2014 at 01:38:40PM +0100, S??bastien Marie wrote:
> Hi,
>
> Starting to play with afl-fuzz, I test it with dc(1), and it found a "Bus
> error".
>
> Basically:
> $ echo '1 2:x1Lx1:x1:x' | dc
> Bus error (core dumped)
>
> I traced the bug, and the code before do a double-free (resulting the
> Bus error). Thanks to malloc(3) junk :)
Thanks, good catch! I'll be checking your fix later,
-Otto
>
> The problem is a lack of initialisation in stack_pushnumber function.
>
> The code before will:
> - allocate an array on register (call it A)
> A[1] = 2
>
> - push it on the stack
> (the array A arrive on stack)
>
> - store it in a new array on register (call it B)
> (the stack is just reduced, the value.array is keeped as it, so
> address of A is here)
> B[1] = A
>
> - push a number on stack
> (as the value isn't properly reinitialized, the number is allocated,
> but the value.array A is keeped)
>
> - allocate an array on register
> - it pops the number (with value.array setted to A), and as it pops,
> it free the value on stack, and the array A too (as != NULL)
> - it pops the array B
> - it will try to set B[1] = 1, so it free B[1], which is A, which is
> already freed: *boom*.
>
> The patch just ensure a push_number (or push_string) properly initialize
> the value, by set value.array to NULL.
> --
> S??bastien Marie
>
> Index: stack.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/dc/stack.c,v
> retrieving revision 1.11
> diff -u -p -r1.11 stack.c
> --- stack.c 27 Oct 2009 23:59:37 -0000 1.11
> +++ stack.c 24 Nov 2014 12:31:53 -0000
> @@ -147,6 +147,7 @@ stack_pushnumber(struct stack *stack, st
> stack_grow(stack);
> stack->stack[stack->sp].type = BCODE_NUMBER;
> stack->stack[stack->sp].u.num = b;
> + stack->stack[stack->sp].array = NULL;
> }
>
> void
> @@ -155,6 +156,7 @@ stack_pushstring(struct stack *stack, ch
> stack_grow(stack);
> stack->stack[stack->sp].type = BCODE_STRING;
> stack->stack[stack->sp].u.string = string;
> + stack->stack[stack->sp].array = NULL;
> }
>
> void