Mercurial > projects > ldc
comparison dmd/root/root.c @ 1640:9bf06e02070b
Merge DMD 1.057.
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Mon, 08 Mar 2010 21:39:20 +0100 |
parents | def7a1d494fd |
children |
comparison
equal
deleted
inserted
replaced
1639:41145d30acb8 | 1640:9bf06e02070b |
---|---|
1 | 1 |
2 // Copyright (c) 1999-2009 by Digital Mars | 2 // Copyright (c) 1999-2010 by Digital Mars |
3 // All Rights Reserved | 3 // All Rights Reserved |
4 // written by Walter Bright | 4 // written by Walter Bright |
5 // www.digitalmars.com | 5 // http://www.digitalmars.com |
6 // License for redistribution is by either the Artistic License | 6 // License for redistribution is by either the Artistic License |
7 // in artistic.txt, or the GNU General Public License in gnu.txt. | 7 // in artistic.txt, or the GNU General Public License in gnu.txt. |
8 // See the included readme.txt for details. | 8 // See the included readme.txt for details. |
9 | 9 |
10 #ifndef POSIX | 10 #ifndef POSIX |
12 #endif | 12 #endif |
13 | 13 |
14 #include <stdio.h> | 14 #include <stdio.h> |
15 #include <stdlib.h> | 15 #include <stdlib.h> |
16 #include <stdarg.h> | 16 #include <stdarg.h> |
17 #include <limits.h> | |
17 #include <string.h> | 18 #include <string.h> |
18 #include <stdint.h> | 19 #include <stdint.h> |
19 #include <assert.h> | 20 #include <assert.h> |
20 | 21 |
21 #if (defined (__SVR4) && defined (__sun)) | 22 #if (defined (__SVR4) && defined (__sun)) |
817 } | 818 } |
818 } | 819 } |
819 return NULL; | 820 return NULL; |
820 } | 821 } |
821 | 822 |
823 | |
824 /************************************* | |
825 * Search Path for file in a safe manner. | |
826 * | |
827 * Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory | |
828 * ('Path Traversal') attacks. | |
829 * http://cwe.mitre.org/data/definitions/22.html | |
830 * More info: | |
831 * https://www.securecoding.cert.org/confluence/display/seccode/FIO02-C.+Canonicalize+path+names+originating+from+untrusted+sources | |
832 * Returns: | |
833 * NULL file not found | |
834 * !=NULL mem.malloc'd file name | |
835 */ | |
836 | |
837 char *FileName::safeSearchPath(Array *path, const char *name) | |
838 { | |
839 #if _WIN32 | |
840 /* Disallow % / \ : and .. in name characters | |
841 */ | |
842 for (const char *p = name; *p; p++) | |
843 { | |
844 char c = *p; | |
845 if (c == '\\' || c == '/' || c == ':' || c == '%' || | |
846 (c == '.' && p[1] == '.')) | |
847 { | |
848 return NULL; | |
849 } | |
850 } | |
851 | |
852 return FileName::searchPath(path, name, 0); | |
853 #elif POSIX | |
854 /* Even with realpath(), we must check for // and disallow it | |
855 */ | |
856 for (const char *p = name; *p; p++) | |
857 { | |
858 char c = *p; | |
859 if (c == '/' && p[1] == '/') | |
860 { | |
861 return NULL; | |
862 } | |
863 } | |
864 | |
865 if (path) | |
866 { unsigned i; | |
867 | |
868 /* Each path is converted to a cannonical name and then a check is done to see | |
869 * that the searched name is really a child one of the the paths searched. | |
870 */ | |
871 for (i = 0; i < path->dim; i++) | |
872 { | |
873 char *cname = NULL; | |
874 char *cpath = canonicalName((char *)path->data[i]); | |
875 //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n", | |
876 // name, (char *)path->data[i], cpath); | |
877 if (cpath == NULL) | |
878 goto cont; | |
879 cname = canonicalName(combine(cpath, name)); | |
880 //printf("FileName::safeSearchPath(): cname=%s\n", cname); | |
881 if (cname == NULL) | |
882 goto cont; | |
883 //printf("FileName::safeSearchPath(): exists=%i " | |
884 // "strncmp(cpath, cname, %i)=%i\n", exists(cname), | |
885 // strlen(cpath), strncmp(cpath, cname, strlen(cpath))); | |
886 // exists and name is *really* a "child" of path | |
887 if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0) | |
888 { | |
889 free(cpath); | |
890 char *p = mem.strdup(cname); | |
891 free(cname); | |
892 return p; | |
893 } | |
894 cont: | |
895 if (cpath) | |
896 free(cpath); | |
897 if (cname) | |
898 free(cname); | |
899 } | |
900 } | |
901 return NULL; | |
902 #else | |
903 assert(0); | |
904 #endif | |
905 } | |
906 | |
907 | |
822 int FileName::exists(const char *name) | 908 int FileName::exists(const char *name) |
823 { | 909 { |
824 #if POSIX | 910 #if POSIX |
825 struct stat st; | 911 struct stat st; |
826 | 912 |
883 error("cannot create directory %s", path); | 969 error("cannot create directory %s", path); |
884 } | 970 } |
885 } | 971 } |
886 } | 972 } |
887 } | 973 } |
974 | |
975 | |
976 /****************************************** | |
977 * Return canonical version of name in a malloc'd buffer. | |
978 * This code is high risk. | |
979 */ | |
980 char *FileName::canonicalName(const char *name) | |
981 { | |
982 #if linux | |
983 // Lovely glibc extension to do it for us | |
984 return canonicalize_file_name(name); | |
985 #elif POSIX | |
986 #if _POSIX_VERSION >= 200809L || defined (linux) | |
987 // NULL destination buffer is allowed and preferred | |
988 return realpath(name, NULL); | |
989 #else | |
990 char *cname = NULL; | |
991 #if PATH_MAX | |
992 /* PATH_MAX must be defined as a constant in <limits.h>, | |
993 * otherwise using it is unsafe due to TOCTOU | |
994 */ | |
995 size_t path_max = (size_t)PATH_MAX; | |
996 if (path_max > 0) | |
997 { | |
998 /* Need to add one to PATH_MAX because of realpath() buffer overflow bug: | |
999 * http://isec.pl/vulnerabilities/isec-0011-wu-ftpd.txt | |
1000 */ | |
1001 cname = (char *)malloc(path_max + 1); | |
1002 if (cname == NULL) | |
1003 return NULL; | |
1004 } | |
1005 #endif | |
1006 return realpath(name, cname); | |
1007 #endif | |
1008 #elif _WIN32 | |
1009 /* Apparently, there is no good way to do this on Windows. | |
1010 * GetFullPathName isn't it. | |
1011 */ | |
1012 assert(0); | |
1013 return NULL; | |
1014 #else | |
1015 assert(0); | |
1016 return NULL; | |
1017 #endif | |
1018 } | |
1019 | |
888 | 1020 |
889 /****************************** File ********************************/ | 1021 /****************************** File ********************************/ |
890 | 1022 |
891 File::File(FileName *n) | 1023 File::File(FileName *n) |
892 { | 1024 { |