http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59358

            Bug ID: 59358
           Summary: Infinite loop generated with >=O2
           Product: gcc
           Version: 4.8.2
            Status: UNCONFIRMED
          Severity: major
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: cJ-gcc at zougloub dot eu

So, we have the following code:

void *lst_realloc(void *, int);

typedef struct smartlist_t {
 void **list;
 int num_used;
 int capacity;
} smartlist_t;

#define MAX_CAPACITY 32

void smartlist_ensure_capacity(smartlist_t *sl, int size) {
    if (size > sl->capacity) {
        int higher = sl->capacity;
        if (size > (int)MAX_CAPACITY/2) {
            higher = MAX_CAPACITY;
        }
        else {
            while (size > higher) {
                higher *= 2;
            }
        }
        sl->capacity = higher;
        sl->list = lst_realloc(sl->list, sl->capacity);
    }
}

Compiling that:
$ x86_64-pc-linux-gnu-gcc-4.8.2 -Os -S -o test.s test.c

Gives:

    pushq    %rbx
    cmpl    12(%rdi), %esi
    movq    %rdi, %rbx
    jle    .L1
    cmpl    $16, %esi
    jg    .L3
.L4:
    jmp    .L4 <----- unexpected infinite loop if size <= capacity/2
.L3:
    movl    $32, 12(%rdi)
    movq    (%rdi), %rdi
    movl    $32, %esi
    call    lst_realloc
    movq    %rax, (%rbx)
.L1:
    popq    %rbx
    ret

Originally from the smartlist_ensure_capacity() function from TOR:
https://gitweb.torproject.org/tor.git/blob/e65b54ec75e3c9e9ada33c8f3ee868d1bea167f5:/src/common/container.c#l61
TOR bug: https://trac.torproject.org/projects/tor/ticket/10259

Reduced by o11c (https://gist.github.com/o11c/7729355) and got help from
pinskia.

Reply via email to