Changeset 396
- Timestamp:
- 02/22/10 01:59:19 (2 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/rtlsym.h (modified) (2 diffs)
- branches/dmd-1.x/src/expression.c (modified) (1 diff)
- branches/dmd-1.x/src/root/root.c (modified) (4 diffs)
- branches/dmd-1.x/src/root/root.h (modified) (2 diffs)
- trunk/src/expression.c (modified) (1 diff)
- trunk/src/root/root.c (modified) (4 diffs)
- trunk/src/root/root.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/rtlsym.h
r251 r396 48 48 SYMBOL_MARS(DCOVER, FLfunc,FREGSAVED,"_d_cover_register", 0, t) \ 49 49 SYMBOL_MARS(DASSERT, FLfunc,FREGSAVED,"_d_assert", SFLexit, t) \ 50 SYMBOL_MARS(DASSERTM, FLfunc,FREGSAVED,"_d_assertm", SFLexit, t) \ 50 51 SYMBOL_MARS(DASSERT_MSG, FLfunc,FREGSAVED,"_d_assert_msg", SFLexit, t) \ 51 52 SYMBOL_MARS(DARRAY, FLfunc,FREGSAVED,"_d_array_bounds", SFLexit, t) \ … … 69 70 SYMBOL_MARS(SWITCH_USTRING,FLfunc,FREGSAVED,"_d_switch_ustring", 0, t) \ 70 71 SYMBOL_MARS(SWITCH_DSTRING,FLfunc,FREGSAVED,"_d_switch_dstring", 0, t) \ 71 SYMBOL_MARS(DSWITCHERR, FLfunc,FREGSAVED,"_d_switch_error", 0, t) \72 SYMBOL_MARS(DSWITCHERR, FLfunc,FREGSAVED,"_d_switch_error", SFLexit, t) \ 72 73 SYMBOL_MARS(DHIDDENFUNC, FLfunc,FREGSAVED,"_d_hidden_func", 0, t) \ 73 74 SYMBOL_MARS(NEWCLASS, FLfunc,FREGSAVED,"_d_newclass", 0, t) \ branches/dmd-1.x/src/expression.c
r389 r396 5265 5265 */ 5266 5266 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); 5284 5268 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()); 5286 5270 goto Lerror; 5287 5271 } branches/dmd-1.x/src/root/root.c
r196 r396 1 1 2 // Copyright (c) 1999-20 09by Digital Mars2 // Copyright (c) 1999-2010 by Digital Mars 3 3 // All Rights Reserved 4 4 // written by Walter Bright 5 // www.digitalmars.com5 // http://www.digitalmars.com 6 6 // License for redistribution is by either the Artistic License 7 7 // in artistic.txt, or the GNU General Public License in gnu.txt. … … 13 13 #include <stdlib.h> 14 14 #include <stdarg.h> 15 #include <limits.h> 15 16 #include <string.h> 16 17 #include <stdint.h> … … 811 812 } 812 813 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 828 char *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 } 885 cont: 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 813 899 int FileName::exists(const char *name) 814 900 { … … 877 963 } 878 964 } 965 966 967 /****************************************** 968 * Return canonical version of name in a malloc'd buffer. 969 * This code is high risk. 970 */ 971 char *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 879 1011 880 1012 /****************************** File ********************************/ branches/dmd-1.x/src/root/root.h
r189 r396 1 1 2 2 3 // Copyright (c) 1999-20 06by Digital Mars3 // Copyright (c) 1999-2010 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 // www.digitalmars.com6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. … … 149 149 void CopyTo(FileName *to); 150 150 static char *searchPath(Array *path, const char *name, int cwd); 151 static char *safeSearchPath(Array *path, const char *name); 151 152 static int exists(const char *name); 152 153 static void ensurePathExists(const char *path); 154 static char *canonicalName(const char *name); 153 155 }; 154 156 trunk/src/expression.c
r392 r396 5607 5607 */ 5608 5608 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); 5626 5610 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()); 5628 5612 goto Lerror; 5629 5613 } trunk/src/root/root.c
r195 r396 1 1 2 // Copyright (c) 1999-20 09by Digital Mars2 // Copyright (c) 1999-2010 by Digital Mars 3 3 // All Rights Reserved 4 4 // written by Walter Bright 5 // www.digitalmars.com5 // http://www.digitalmars.com 6 6 // License for redistribution is by either the Artistic License 7 7 // in artistic.txt, or the GNU General Public License in gnu.txt. … … 13 13 #include <stdlib.h> 14 14 #include <stdarg.h> 15 #include <limits.h> 15 16 #include <string.h> 16 17 #include <stdint.h> … … 811 812 } 812 813 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 828 char *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 } 885 cont: 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 813 899 int FileName::exists(const char *name) 814 900 { … … 877 963 } 878 964 } 965 966 967 /****************************************** 968 * Return canonical version of name in a malloc'd buffer. 969 * This code is high risk. 970 */ 971 char *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 879 1011 880 1012 /****************************** File ********************************/ trunk/src/root/root.h
r189 r396 1 1 2 2 3 // Copyright (c) 1999-20 06by Digital Mars3 // Copyright (c) 1999-2010 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 // www.digitalmars.com6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. … … 149 149 void CopyTo(FileName *to); 150 150 static char *searchPath(Array *path, const char *name, int cwd); 151 static char *safeSearchPath(Array *path, const char *name); 151 152 static int exists(const char *name); 152 153 static void ensurePathExists(const char *path); 154 static char *canonicalName(const char *name); 153 155 }; 154 156
