Bug 10911 - crash due to -D_FORTIFY_SOURCE=2 false positive
: crash due to -D_FORTIFY_SOURCE=2 false positive
Status: CLOSED FIXED
: Sisyphus
(All bugs in Sisyphus/vim-console)
: unstable
: all Linux
: P2 critical
Assigned To:
:
:
:
:
:
  Show dependency tree
 
Reported: 2007-02-23 14:22 by
Modified: 2007-03-18 01:12 (History)


Attachments


Note

You need to log in before you can comment on or make changes to this bug.


Description From 2007-02-23 14:22:34
vim (все полнофункциональные варианты, не только vim-console) падает при
выполнении примера из ":help self":

        :function Mylen() dict
        :   return len(self.data)
        :endfunction
        :let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
        :echo mydict.len()

#0  0x00002aaaacd333a5 in raise () from /lib64/libc.so.6
#1  0x00002aaaacd34730 in abort () from /lib64/libc.so.6
#2  0x00002aaaacd68ebb in __fsetlocking () from /lib64/libc.so.6
#3  0x00002aaaacdd04ff in __chk_fail () from /lib64/libc.so.6
#4  0x0000000000457a64 in call_func (name=0x857e90 "Mylen", len=Variable "len"
is not available.
) at eval.c:19832
#5  0x000000000045a8dc in get_func_tv (name=0x857e90 "Mylen", len=5,
rettv=0x7fff452d7cd0, arg=0x7fff452d7ce8, firstline=494, 
    lastline=494, doesrange=0x7fff452d77fc, evaluate=1, selfdict=0x921410) at
eval.c:7411
#6  0x000000000045aacb in handle_subscript (arg=0x7fff452d7ce8,
rettv=0x7fff452d7cd0, evaluate=1, verbose=1) at eval.c:17185
#7  0x000000000045be48 in eval7 (arg=0x7fff452d7ce8, rettv=0x7fff452d7cd0,
evaluate=1) at eval.c:4701
#8  0x000000000045c6a4 in eval6 (arg=0x7fff452d7ce8, rettv=0x7fff452d7cd0,
evaluate=1) at eval.c:4442
#9  0x000000000045927f in eval5 (arg=0x7fff452d7ce8, rettv=0x7fff452d7cd0,
evaluate=1) at eval.c:4311
#10 0x00000000004594f6 in eval4 (arg=0x7fff452d7ce8, rettv=0x7fff452d7cd0,
evaluate=1) at eval.c:4043
#11 0x0000000000459c24 in eval3 (arg=0x7fff452d7ce8, rettv=0x7fff452d7cd0,
evaluate=1) at eval.c:3955
#12 0x0000000000459d74 in eval1 (arg=0x7fff452d7ce8, rettv=0x7fff452d7cd0,
evaluate=1) at eval.c:3884
#13 0x000000000045a042 in ex_echo (eap=0x7fff452d7e50) at eval.c:18150
#14 0x000000000047d974 in do_one_cmd (cmdlinep=0x7fff452d8068, sourcing=0,
cstack=0x7fff452d8070, fgetline=0x48bad0 <getexline>, 
    cookie=0x0) at ex_docmd.c:2616
#15 0x000000000047eda9 in do_cmdline (cmdline=Variable "cmdline" is not
available.
) at ex_docmd.c:1098
#16 0x00000000004e8352 in nv_colon (cap=0x7fff452d85b0) at normal.c:5161
#17 0x00000000004ea9d3 in normal_cmd (oap=0x7fff452d8650, toplevel=1) at
normal.c:1136
#18 0x00000000004affbf in main_loop (cmdwin=0, noexmode=0) at main.c:1154
#19 0x00000000004b301a in main (argc=Variable "argc" is not available.
) at main.c:934

При сборке vim обнаружилось предупреждение:

eval.c: In function 'call_func':
eval.c:19832: warning: call to __builtin___strcpy_chk will always overflow
destination buffer

Ситуация следующая: тип dictitem_T объявлен как:

/*
 * Structure to hold an item of a Dictionary.
 * Also used for a variable.
 * The key is copied into "di_key" to avoid an extra alloc/free for it.
 */
struct dictitem_S
{
    typval_T    di_tv;        /* type and value of the variable */
    char_u    di_flags;    /* flags (only used for variable) */
    char_u    di_key[1];    /* key (actually longer!) */
};

typedef struct dictitem_S dictitem_T;

При этом в eval.c:call_user_func() имеется следующий код:

    funccall_T    fc;
    dictitem_T    *v;
    char_u    *name;
...
    /* Set l:self to "selfdict".  Use "name" to avoid a warning from
     * some compiler that checks the destination size. */
    v = &fc.fixvar[fixvar_idx++].var;
    name = v->di_key;
    STRCPY(name, "self");

Однако даже использование промежуточной переменной name не помогает скрыть от
компилятора то, что копирование происходит в поле di_key, которое объявлено как
массив из 1 элемента. Вероятно, играет роль и то, что структура funccall_S
определена весьма специфическим образом:

struct funccall_S
{
...
    struct            /* fixed variables for arguments */
    {
    dictitem_T    var;        /* variable (without room for name) */
    char_u    room[VAR_SHORT_LEN];    /* room for the name */
    } fixvar[FIXVAR_CNT];
...
};

Т.е., в данном случае код написан с расчётом на то, что var.di_name будет
переполнено с залезанием в room.
------- Comment #1 From 2007-02-23 20:51:32 -------
Патч из OpenSUSE нашёл, заслал проблему в обстрём, посмотрим что будет...
------- Comment #2 From 2007-02-24 12:38:56 -------
На самом деле это, конечно, не -fstack-protector, а -D_FORTIFY_SOURCE=2.
------- Comment #3 From 2007-02-24 13:23:20 -------
Апстрим послал меня чинить gcc и ставить релиз glibc вместо "unfinished and
contains bugs" снапшота.  В следующей сборке приложу патч, посмотрим что
будет...
------- Comment #4 From 2007-03-18 01:12:12 -------
Fixed in 4:7.0.218-alt1