Branch: Tag:

2016-06-17

2016-06-17 15:39:06 by Henrik Grubbström (Grubba) <grubba@grubba.org>

combine_path: Survive string_builder without NUL-terminations.

The string_builder API no longer maintains NUL-termination of the
buffer. This caused combine_path_nt() et al to fail intermittently
due to reading past the buffer end.

Also adds a corresponding test.

Fixes [bug 7723 (#7723)].

22: Inside #if defined(UNIX_COMBINE_PATH)
     #ifdef UNIX_COMBINE_PATH   #define IS_SEP(X) ( (X)=='/' ) - #define IS_ABS(X) (IS_SEP( INDEX_PCHARP((X),0))?1:0) + #define IS_ABS(X, L) ((((L) > 0) && IS_SEP(INDEX_PCHARP((X),0)))?1:0)   #define APPEND_PATH append_path_unix   #define COMBINE_PATH combine_path_unix   #define CHAR_CURRENT '.'
34:   #ifdef NT_COMBINE_PATH   #define IS_SEP(X) ( (X) == '/' || (X) == '\\' )    - static int find_absolute(PCHARP s) + static int find_absolute(PCHARP s, ptrdiff_t len)   {    int c0=INDEX_PCHARP(s,0);    int c1=c0?INDEX_PCHARP(s,1):0;
45:    * correct. */    if(((c0 >= 'A' && c0 <= 'Z') ||    (c0 >= 'a' && c0 <= 'z')) && -  c1==':' && IS_SEP(INDEX_PCHARP(s,2))) +  c1==':' && IS_SEP(INDEX_PCHARP(s,2)) && (len >= 3))    return 3;    -  if(IS_SEP(c0) && IS_SEP(c1)) +  if(IS_SEP(c0) && IS_SEP(c1) && (len >= 2))    {    int l;    for(l=2;INDEX_PCHARP(s,l) && !IS_SEP(INDEX_PCHARP(s,l));l++);
57:       return 0;   } - #define IS_ABS(X) find_absolute((X)) - #define IS_ROOT(X) ( IS_SEP( INDEX_PCHARP((X),0) )?1:0) + #define IS_ABS(X, L) find_absolute((X), (L)) + #define IS_ROOT(X, L) ( (((L) > 0) && IS_SEP( INDEX_PCHARP((X),0) ))?1:0)      #define APPEND_PATH append_path_nt   #define COMBINE_PATH combine_path_nt
72:   #ifdef AMIGAOS_COMBINE_PATH   #define IS_SEP(X) ( (X)=='/' )   #define IS_ANY_SEP(X) ( (X) == '/' || (X) == ':' ) - #define IS_ABS(X) find_absolute2((X)) - #define IS_ROOT(X) ( ( INDEX_PCHARP((X),0) == CHAR_ROOT)?1:0) + #define IS_ABS(X, L) find_absolute2((X), (L)) + #define IS_ROOT(X, L) ( ((L) > 0) && ( INDEX_PCHARP((X),0) == CHAR_ROOT)?1:0)   #define APPEND_PATH append_path_amigaos   #define COMBINE_PATH combine_path_amigaos   #define CHAR_ROOT ':'    - static int find_absolute2(PCHARP s) + static int find_absolute2(PCHARP s, ptrdiff_t len)   {    int r=0, p=0;    int c; -  while((c=INDEX_PCHARP(s,p))) { +  while((c=INDEX_PCHARP(s,p)) && (len > 0)) {    ++p; -  +  --len;    if(c == CHAR_ROOT)    r = p;    }
107:    /* First, check if path is absolute,    * if so ignore anything already in 's'    */ -  abs=IS_ABS(MKPCHARP_STR(s->s)); -  if((tmp=IS_ABS(path))) +  abs=IS_ABS(MKPCHARP_STR(s->s), s->s->len); +  if((tmp=IS_ABS(path, len)))    {    s->s->len=0;    s->known_shift=0;
117:    abs=tmp;    }   #ifdef IS_ROOT -  else if((tmp=IS_ROOT(path))) +  else if((tmp=IS_ROOT(path, len)))    {    int tmp2;    s->known_shift=0; -  if((tmp2=IS_ABS(MKPCHARP_STR(s->s)))) +  if((tmp2=IS_ABS(MKPCHARP_STR(s->s), s->s->len)))    {    s->s->len=tmp2;    abs=tmp2;
159:    while(1)    {   #if COMBINE_PATH_DEBUG > 1 -  s->s->str[s->s->len]=0; -  fprintf(stderr, "combine_path(2), TO: \"%s\"\n", s->s->str); -  fprintf(stderr, "combine_path(2), FROM (%d): \"%s\"\n", -  from, path.ptr+from); +  /* s->s->str[s->s->len]=0; */ +  fprintf(stderr, "combine_path(2), TO: \"%s\"[%d]\n", s->s->str, s->s->len); +  fprintf(stderr, "combine_path(2), FROM (%d): \"%s\"[%d]\n", +  from, path.ptr+from, len - from);   #endif    if(IS_SEP(LAST_PUSHED()))    {
186:    {    int c3;   #if COMBINE_PATH_DEBUG > 0 -  s->s->str[s->s->len]=0; -  fprintf(stderr, "combine_path(0), TO: \"%s\"\n", s->s->str); -  fprintf(stderr, "combine_path(0), FROM (%d): \"%s\"\n", -  from, path.ptr+from); +  /* s->s->str[s->s->len]=0; */ +  fprintf(stderr, "combine_path(0), TO: \"%s\"[%d]\n", +  s->s->str, s->s->len); +  fprintf(stderr, "combine_path(0), FROM (%d): \"%s\"[%d]\n", +  from, path.ptr+from, len - from);   #endif       switch(INDEX_PCHARP(path, from+1))
224:    s->known_shift=0;      #if COMBINE_PATH_DEBUG > 0 -  s->s->str[s->s->len]=0; -  fprintf(stderr,"combine_path(1), TO: %s\n",s->s->str); -  fprintf(stderr,"combine_path(1), FROM (%d): %s\n",from,path.ptr+from); +  /* s->s->str[s->s->len]=0; */ +  fprintf(stderr,"combine_path(1), TO: %s[%d]\n", +  s->s->str, s->s->len); +  fprintf(stderr,"combine_path(1), FROM (%d): %s[%d]\n", +  from, path.ptr+from, len-from);   #endif    continue;    }
283:    init_string_builder(&ret, 0);    SET_ONERROR(tmp, free_string_builder, &ret);    + #if COMBINE_PATH_DEBUG > 0 +  for(e=0; e < args; e++) { +  fprintf(stderr, "combine_path(), Arg #%d: \"%s\"[%d bytes]\n", +  e, Pike_sp[e-args].u.string->str, Pike_sp[e-args].u.string->len); +  } + #endif + #if COMBINE_PATH_DEBUG > 5 +  fprintf(stderr, "combine_path(), Empty: \"%s\"[%d bytes]\n", +  ret.s->str, ret.s->len); +  fprintf(stderr, "combine_path(), Empty+1: \"%s\"\n", +  ret.s->str+1); + #endif +     for(e=args-1;e>root;e--)    { -  if(IS_ABS(MKPCHARP_STR(Pike_sp[e-args].u.string))) +  if(IS_ABS(MKPCHARP_STR(Pike_sp[e-args].u.string), +  Pike_sp[e-args].u.string->len))    {    root=e;    break;
297:    Pike_sp[root-args].u.string->len);    root++;    + #if COMBINE_PATH_DEBUG > 1 +  fprintf(stderr, "combine_path(), ret: \"%s\"[%d] (root: %d)\n", +  ret.s->str, ret.s->len, root); + #endif +    #ifdef IS_ROOT    for(e=args-1;e>root;e--)    { -  if(IS_ROOT(MKPCHARP_STR(Pike_sp[e-args].u.string))) +  if (TYPEOF(Pike_sp[e-args]) != T_STRING) continue; +  if(IS_ROOT(MKPCHARP_STR(Pike_sp[e-args].u.string), +  Pike_sp[e-args].u.string->len))    {    root=e;    break;    }    } -  + #if COMBINE_PATH_DEBUG > 1 +  fprintf(stderr, "combine_path(), root: %d\n", root);   #endif -  + #endif       while(root<args)    { -  +  if (TYPEOF(Pike_sp[root-args]) != T_STRING) continue; + #if COMBINE_PATH_DEBUG > 0 +  fprintf(stderr, "combine_path(), Appending \"%s\"[%d] root: %d\n", +  Pike_sp[root-args].u.string->str, +  Pike_sp[root-args].u.string->len, +  root); + #endif    APPEND_PATH(&ret,    MKPCHARP_STR(Pike_sp[root-args].u.string),    Pike_sp[root-args].u.string->len);
321:   }       -  + #undef COMBINE_PATH_DEBUG   #undef UNIX_COMBINE_PATH   #undef NT_COMBINE_PATH   #undef AMIGAOS_COMBINE_PATH