Changeset 396

Show
Ignore:
Timestamp:
02/22/10 01:59:19 (2 years ago)
Author:
walter
Message:

bugzilla 3420 [PATCH] Allow string import of files using subdirectories

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/dmd-1.x/src/backend/rtlsym.h

    r251 r396  
    4848SYMBOL_MARS(DCOVER,      FLfunc,FREGSAVED,"_d_cover_register", 0, t) \ 
    4949SYMBOL_MARS(DASSERT,         FLfunc,FREGSAVED,"_d_assert", SFLexit, t) \ 
     50SYMBOL_MARS(DASSERTM,        FLfunc,FREGSAVED,"_d_assertm", SFLexit, t) \ 
    5051SYMBOL_MARS(DASSERT_MSG,     FLfunc,FREGSAVED,"_d_assert_msg", SFLexit, t) \ 
    5152SYMBOL_MARS(DARRAY,      FLfunc,FREGSAVED,"_d_array_bounds", SFLexit, t) \ 
     
    6970SYMBOL_MARS(SWITCH_USTRING,FLfunc,FREGSAVED,"_d_switch_ustring", 0, t) \ 
    7071SYMBOL_MARS(SWITCH_DSTRING,FLfunc,FREGSAVED,"_d_switch_dstring", 0, t) \ 
    71 SYMBOL_MARS(DSWITCHERR,    FLfunc,FREGSAVED,"_d_switch_error", 0, t) \ 
     72SYMBOL_MARS(DSWITCHERR,    FLfunc,FREGSAVED,"_d_switch_error", SFLexit, t) \ 
    7273SYMBOL_MARS(DHIDDENFUNC,   FLfunc,FREGSAVED,"_d_hidden_func", 0, t) \ 
    7374SYMBOL_MARS(NEWCLASS,      FLfunc,FREGSAVED,"_d_newclass", 0, t) \ 
  • branches/dmd-1.x/src/expression.c

    r389 r396  
    52655265     */ 
    52665266 
    5267     /* Do harsh sanitizing by limiting the name's character set. 
    5268      */ 
    5269     for (const char *p = name; *p; p++) 
    5270     { 
    5271     if (!(isalnum(*p) || *p == '.' || *p == '_')) 
    5272     { 
    5273         error("file name characters are restricted to [a-zA-Z0-9._] not '%c'", *p); 
    5274         goto Lerror; 
    5275     } 
    5276     } 
    5277  
    5278     if (name != FileName::name(name)) 
    5279     {   error("use -Jpath switch to provide path for filename %s", name); 
    5280     goto Lerror; 
    5281     } 
    5282  
    5283     name = FileName::searchPath(global.filePath, name, 0); 
     5267    name = FileName::safeSearchPath(global.filePath, name); 
    52845268    if (!name) 
    5285     {   error("file %s cannot be found, check -Jpath", se->toChars()); 
     5269    {   error("file %s cannot be found or not in a path specified with -J", se->toChars()); 
    52865270    goto Lerror; 
    52875271    } 
  • branches/dmd-1.x/src/root/root.c

    r196 r396  
    11 
    2 // Copyright (c) 1999-2009 by Digital Mars 
     2// Copyright (c) 1999-2010 by Digital Mars 
    33// All Rights Reserved 
    44// written by Walter Bright 
    5 // www.digitalmars.com 
     5// http://www.digitalmars.com 
    66// License for redistribution is by either the Artistic License 
    77// in artistic.txt, or the GNU General Public License in gnu.txt. 
     
    1313#include <stdlib.h> 
    1414#include <stdarg.h> 
     15#include <limits.h> 
    1516#include <string.h> 
    1617#include <stdint.h> 
     
    811812} 
    812813 
     814 
     815/************************************* 
     816 * Search Path for file in a safe manner. 
     817 * 
     818 * Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory 
     819 * ('Path Traversal') attacks. 
     820 *  http://cwe.mitre.org/data/definitions/22.html 
     821 * More info: 
     822 *  https://www.securecoding.cert.org/confluence/display/seccode/FIO02-C.+Canonicalize+path+names+originating+from+untrusted+sources 
     823 * Returns: 
     824 *  NULL    file not found 
     825 *  !=NULL  mem.malloc'd file name 
     826 */ 
     827 
     828char *FileName::safeSearchPath(Array *path, const char *name) 
     829{ 
     830#if _WIN32 
     831    /* Disallow % / \ : and .. in name characters 
     832     */ 
     833    for (const char *p = name; *p; p++) 
     834    { 
     835    char c = *p; 
     836    if (c == '\\' || c == '/' || c == ':' || c == '%' || 
     837        (c == '.' && p[1] == '.')) 
     838    { 
     839        return NULL; 
     840    } 
     841    } 
     842 
     843    return FileName::searchPath(path, name, 0); 
     844#elif POSIX 
     845    /* Even with realpath(), we must check for // and disallow it 
     846     */ 
     847    for (const char *p = name; *p; p++) 
     848    { 
     849    char c = *p; 
     850    if (c == '/' && p[1] == '/') 
     851    { 
     852        return NULL; 
     853    } 
     854    } 
     855 
     856    if (path) 
     857    {   unsigned i; 
     858 
     859    /* Each path is converted to a cannonical name and then a check is done to see 
     860     * that the searched name is really a child one of the the paths searched. 
     861     */ 
     862    for (i = 0; i < path->dim; i++) 
     863    { 
     864        char *cname = NULL; 
     865        char *cpath = canonicalName((char *)path->data[i]); 
     866        //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n", 
     867        //      name, (char *)path->data[i], cpath); 
     868        if (cpath == NULL) 
     869        goto cont; 
     870        cname = canonicalName(combine(cpath, name)); 
     871        //printf("FileName::safeSearchPath(): cname=%s\n", cname); 
     872        if (cname == NULL) 
     873        goto cont; 
     874        //printf("FileName::safeSearchPath(): exists=%i " 
     875        //      "strncmp(cpath, cname, %i)=%i\n", exists(cname), 
     876        //      strlen(cpath), strncmp(cpath, cname, strlen(cpath))); 
     877        // exists and name is *really* a "child" of path 
     878        if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0) 
     879        { 
     880        free(cpath); 
     881        char *p = mem.strdup(cname); 
     882        free(cname); 
     883        return p; 
     884        } 
     885cont: 
     886        if (cpath) 
     887        free(cpath); 
     888        if (cname) 
     889        free(cname); 
     890    } 
     891    } 
     892    return NULL; 
     893#else 
     894    assert(0); 
     895#endif 
     896} 
     897 
     898 
    813899int FileName::exists(const char *name) 
    814900{ 
     
    877963    } 
    878964} 
     965 
     966 
     967/****************************************** 
     968 * Return canonical version of name in a malloc'd buffer. 
     969 * This code is high risk. 
     970 */ 
     971char *FileName::canonicalName(const char *name) 
     972{ 
     973#if linux 
     974    // Lovely glibc extension to do it for us 
     975    return canonicalize_file_name(name); 
     976#elif POSIX 
     977  #if _POSIX_VERSION >= 200809L || defined (linux) 
     978    // NULL destination buffer is allowed and preferred 
     979    return realpath(name, NULL); 
     980  #else 
     981    char *cname = NULL; 
     982    #if PATH_MAX 
     983    /* PATH_MAX must be defined as a constant in <limits.h>, 
     984     * otherwise using it is unsafe due to TOCTOU 
     985     */ 
     986    size_t path_max = (size_t)PATH_MAX; 
     987    if (path_max > 0) 
     988    { 
     989        /* Need to add one to PATH_MAX because of realpath() buffer overflow bug: 
     990         * http://isec.pl/vulnerabilities/isec-0011-wu-ftpd.txt 
     991         */ 
     992        cname = (char *)malloc(path_max + 1); 
     993        if (cname == NULL) 
     994        return NULL; 
     995    } 
     996    #endif 
     997    return realpath(name, cname); 
     998  #endif 
     999#elif _WIN32 
     1000    /* Apparently, there is no good way to do this on Windows. 
     1001     * GetFullPathName isn't it. 
     1002     */ 
     1003    assert(0); 
     1004    return NULL; 
     1005#else 
     1006    assert(0); 
     1007    return NULL; 
     1008#endif 
     1009} 
     1010 
    8791011 
    8801012/****************************** File ********************************/ 
  • branches/dmd-1.x/src/root/root.h

    r189 r396  
    11 
    22 
    3 // Copyright (c) 1999-2006 by Digital Mars 
     3// Copyright (c) 1999-2010 by Digital Mars 
    44// All Rights Reserved 
    55// written by Walter Bright 
    6 // www.digitalmars.com 
     6// http://www.digitalmars.com 
    77// License for redistribution is by either the Artistic License 
    88// in artistic.txt, or the GNU General Public License in gnu.txt. 
     
    149149    void CopyTo(FileName *to); 
    150150    static char *searchPath(Array *path, const char *name, int cwd); 
     151    static char *safeSearchPath(Array *path, const char *name); 
    151152    static int exists(const char *name); 
    152153    static void ensurePathExists(const char *path); 
     154    static char *canonicalName(const char *name); 
    153155}; 
    154156 
  • trunk/src/expression.c

    r392 r396  
    56075607     */ 
    56085608 
    5609     /* Do harsh sanitizing by limiting the name's character set. 
    5610      */ 
    5611     for (const char *p = name; *p; p++) 
    5612     { 
    5613     if (!(isalnum(*p) || *p == '.' || *p == '_')) 
    5614     { 
    5615         error("file name characters are restricted to [a-zA-Z0-9._] not '%c'", *p); 
    5616         goto Lerror; 
    5617     } 
    5618     } 
    5619  
    5620     if (name != FileName::name(name)) 
    5621     {   error("use -Jpath switch to provide path for filename %s", name); 
    5622     goto Lerror; 
    5623     } 
    5624  
    5625     name = FileName::searchPath(global.filePath, name, 0); 
     5609    name = FileName::safeSearchPath(global.filePath, name); 
    56265610    if (!name) 
    5627     {   error("file %s cannot be found, check -Jpath", se->toChars()); 
     5611    {   error("file %s cannot be found or not in a path specified with -J", se->toChars()); 
    56285612    goto Lerror; 
    56295613    } 
  • trunk/src/root/root.c

    r195 r396  
    11 
    2 // Copyright (c) 1999-2009 by Digital Mars 
     2// Copyright (c) 1999-2010 by Digital Mars 
    33// All Rights Reserved 
    44// written by Walter Bright 
    5 // www.digitalmars.com 
     5// http://www.digitalmars.com 
    66// License for redistribution is by either the Artistic License 
    77// in artistic.txt, or the GNU General Public License in gnu.txt. 
     
    1313#include <stdlib.h> 
    1414#include <stdarg.h> 
     15#include <limits.h> 
    1516#include <string.h> 
    1617#include <stdint.h> 
     
    811812} 
    812813 
     814 
     815/************************************* 
     816 * Search Path for file in a safe manner. 
     817 * 
     818 * Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory 
     819 * ('Path Traversal') attacks. 
     820 *  http://cwe.mitre.org/data/definitions/22.html 
     821 * More info: 
     822 *  https://www.securecoding.cert.org/confluence/display/seccode/FIO02-C.+Canonicalize+path+names+originating+from+untrusted+sources 
     823 * Returns: 
     824 *  NULL    file not found 
     825 *  !=NULL  mem.malloc'd file name 
     826 */ 
     827 
     828char *FileName::safeSearchPath(Array *path, const char *name) 
     829{ 
     830#if _WIN32 
     831    /* Disallow % / \ : and .. in name characters 
     832     */ 
     833    for (const char *p = name; *p; p++) 
     834    { 
     835    char c = *p; 
     836    if (c == '\\' || c == '/' || c == ':' || c == '%' || 
     837        (c == '.' && p[1] == '.')) 
     838    { 
     839        return NULL; 
     840    } 
     841    } 
     842 
     843    return FileName::searchPath(path, name, 0); 
     844#elif POSIX 
     845    /* Even with realpath(), we must check for // and disallow it 
     846     */ 
     847    for (const char *p = name; *p; p++) 
     848    { 
     849    char c = *p; 
     850    if (c == '/' && p[1] == '/') 
     851    { 
     852        return NULL; 
     853    } 
     854    } 
     855 
     856    if (path) 
     857    {   unsigned i; 
     858 
     859    /* Each path is converted to a cannonical name and then a check is done to see 
     860     * that the searched name is really a child one of the the paths searched. 
     861     */ 
     862    for (i = 0; i < path->dim; i++) 
     863    { 
     864        char *cname = NULL; 
     865        char *cpath = canonicalName((char *)path->data[i]); 
     866        //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n", 
     867        //      name, (char *)path->data[i], cpath); 
     868        if (cpath == NULL) 
     869        goto cont; 
     870        cname = canonicalName(combine(cpath, name)); 
     871        //printf("FileName::safeSearchPath(): cname=%s\n", cname); 
     872        if (cname == NULL) 
     873        goto cont; 
     874        //printf("FileName::safeSearchPath(): exists=%i " 
     875        //      "strncmp(cpath, cname, %i)=%i\n", exists(cname), 
     876        //      strlen(cpath), strncmp(cpath, cname, strlen(cpath))); 
     877        // exists and name is *really* a "child" of path 
     878        if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0) 
     879        { 
     880        free(cpath); 
     881        char *p = mem.strdup(cname); 
     882        free(cname); 
     883        return p; 
     884        } 
     885cont: 
     886        if (cpath) 
     887        free(cpath); 
     888        if (cname) 
     889        free(cname); 
     890    } 
     891    } 
     892    return NULL; 
     893#else 
     894    assert(0); 
     895#endif 
     896} 
     897 
     898 
    813899int FileName::exists(const char *name) 
    814900{ 
     
    877963    } 
    878964} 
     965 
     966 
     967/****************************************** 
     968 * Return canonical version of name in a malloc'd buffer. 
     969 * This code is high risk. 
     970 */ 
     971char *FileName::canonicalName(const char *name) 
     972{ 
     973#if linux 
     974    // Lovely glibc extension to do it for us 
     975    return canonicalize_file_name(name); 
     976#elif POSIX 
     977  #if _POSIX_VERSION >= 200809L || defined (linux) 
     978    // NULL destination buffer is allowed and preferred 
     979    return realpath(name, NULL); 
     980  #else 
     981    char *cname = NULL; 
     982    #if PATH_MAX 
     983    /* PATH_MAX must be defined as a constant in <limits.h>, 
     984     * otherwise using it is unsafe due to TOCTOU 
     985     */ 
     986    size_t path_max = (size_t)PATH_MAX; 
     987    if (path_max > 0) 
     988    { 
     989        /* Need to add one to PATH_MAX because of realpath() buffer overflow bug: 
     990         * http://isec.pl/vulnerabilities/isec-0011-wu-ftpd.txt 
     991         */ 
     992        cname = (char *)malloc(path_max + 1); 
     993        if (cname == NULL) 
     994        return NULL; 
     995    } 
     996    #endif 
     997    return realpath(name, cname); 
     998  #endif 
     999#elif _WIN32 
     1000    /* Apparently, there is no good way to do this on Windows. 
     1001     * GetFullPathName isn't it. 
     1002     */ 
     1003    assert(0); 
     1004    return NULL; 
     1005#else 
     1006    assert(0); 
     1007    return NULL; 
     1008#endif 
     1009} 
     1010 
    8791011 
    8801012/****************************** File ********************************/ 
  • trunk/src/root/root.h

    r189 r396  
    11 
    22 
    3 // Copyright (c) 1999-2006 by Digital Mars 
     3// Copyright (c) 1999-2010 by Digital Mars 
    44// All Rights Reserved 
    55// written by Walter Bright 
    6 // www.digitalmars.com 
     6// http://www.digitalmars.com 
    77// License for redistribution is by either the Artistic License 
    88// in artistic.txt, or the GNU General Public License in gnu.txt. 
     
    149149    void CopyTo(FileName *to); 
    150150    static char *searchPath(Array *path, const char *name, int cwd); 
     151    static char *safeSearchPath(Array *path, const char *name); 
    151152    static int exists(const char *name); 
    152153    static void ensurePathExists(const char *path); 
     154    static char *canonicalName(const char *name); 
    153155}; 
    154156