Index: src/cabextract.c =================================================================== --- src/cabextract.c (revision 216) +++ src/cabextract.c (working copy) @@ -738,7 +738,7 @@ static char *create_output_name(unsigned char *fname, unsigned char *dir, int lower, int isunix, int utf8) { - unsigned char *p, *name, c, *fe, sep, slash; + unsigned char *p, *name, c, *o, *fe, sep, slash; int x; sep = (isunix) ? '/' : '\\'; /* the path-seperator */ @@ -750,7 +750,7 @@ if (utf8) x *= 4; /* length of output directory */ if (dir) x += strlen((char *) dir); - x += 2; + x += 3; if (!(name = malloc(x))) { fprintf(stderr, "Can't allocate output filename (%u bytes)\n", x); @@ -766,16 +766,14 @@ strcat((char *) name, "/"); } - /* remove leading slashes */ - while (*fname == sep) fname++; - /* copy from fi->filename to new name, converting MS-DOS slashes to UNIX * slashes as we go. Also lowercases characters if needed. */ - p = &name[strlen((char *)name)]; /* p = start of output filename */ + p = o = &name[strlen((char *)name)]; /* p = o = start of output filename */ fe = &fname[strlen((char *)fname)]; /* fe = end of input filename */ if (utf8) { + int first = 1; /* handle UTF-8 encoded filenames (see RFC 3629). This doesn't reject bad * UTF-8 with overlong encodings, but does re-encode it as valid UTF-8. */ @@ -815,6 +813,10 @@ x = 0xFFFD; /* invalid code point or cheeky null byte */ } + /* remove leading slashes */ + if (first && x == sep) continue; + first = 0; + /* whatever is the path seperator -> '/' * whatever is the other slash -> '\\' * otherwise, if lower is set, the lowercase version */ @@ -851,6 +853,7 @@ } else { /* regular non-utf8 version */ + while (*fname == sep) fname++; do { c = *fname++; if (c == sep) c = '/'; @@ -861,7 +864,7 @@ /* search for "../" in cab filename part and change to "xx/". This * prevents any unintended directory traversal. */ - for (p = &name[dir ? strlen((char *) dir)+1 : 0]; *p; p++) { + for (p = o; *p; p++) { if ((p[0] == '.') && (p[1] == '.') && (p[2] == '/')) { p[0] = p[1] = 'x'; p += 2; @@ -868,6 +871,11 @@ } } + /* change filename composed entirely of leading slashes to "x" */ + if (strlen(o) == 0) { + strcat(o, "x"); + } + return (char *) name; }