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 {