diff -Naur php-4.2.2/ext/exif/exif.c php-4.2.2.openpkg-patched/ext/exif/exif.c --- php-4.2.2/ext/exif/exif.c 2002-04-10 09:37:49.000000000 +0300 +++ php-4.2.2.openpkg-patched/ext/exif/exif.c 2004-12-22 08:57:52.000000000 +0200 @@ -1343,7 +1343,7 @@ // It is important to check for IMAGE_FILETYPE_TIFF // JPEG does not use absolute pointers instead its pointers are relative to the start // of the TIFF header in APP1 section. - if (offset_val<0 || offset_val+byte_count>ImageInfo->FileSize || (ImageInfo->FileType!=IMAGE_FILETYPE_TIFF_II && ImageInfo->FileType!=IMAGE_FILETYPE_TIFF_MM)) { + if (offset_val<0 || offset_val+byte_count>ImageInfo->FileSize || (ImageInfo->FileType!=IMAGE_FILETYPE_TIFF_II && ImageInfo->FileType!=IMAGE_FILETYPE_TIFF_MM && ImageInfo->FileType!=IMAGE_FILETYPE_JPEG)) { if (value_ptr < dir_entry) { /* we can read this if offset_val > 0 */ /* some files have their values in other parts of the file */ @@ -2163,7 +2163,7 @@ } for (i=0; ivalue.lval > shmop->size ) { + if (offset < 0 || (*offset)->value.lval > shmop->size ) { php_error(E_WARNING, "shmop_write: offset out of range"); RETURN_FALSE; } diff -Naur php-4.2.2/ext/standard/link.c php-4.2.2.openpkg-patched/ext/standard/link.c --- php-4.2.2/ext/standard/link.c 2002-02-28 10:26:46.000000000 +0200 +++ php-4.2.2.openpkg-patched/ext/standard/link.c 2004-12-22 09:02:11.000000000 +0200 @@ -63,6 +63,14 @@ } convert_to_string_ex(filename); + if (PG(safe_mode) && !php_checkuid(Z_STRVAL_PP(filename), NULL, CHECKUID_CHECK_FILE_AND_DIR)) { + RETURN_FALSE; + } + + if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) { + RETURN_FALSE; + } + ret = readlink(Z_STRVAL_PP(filename), buff, 255); if (ret == -1) { php_error(E_WARNING, "readlink failed (%s)", strerror(errno)); diff -Naur php-4.2.2/ext/standard/pack.c php-4.2.2.openpkg-patched/ext/standard/pack.c --- php-4.2.2/ext/standard/pack.c 2002-02-28 10:26:46.000000000 +0200 +++ php-4.2.2.openpkg-patched/ext/standard/pack.c 2004-12-22 08:53:34.000000000 +0200 @@ -49,6 +49,13 @@ #include #endif +#define INC_OUTPUTPOS(a,b) \ + if ((a) < 0 || ((INT_MAX - outputpos)/(b)) < (a)) { \ + php_error(E_WARNING, "Type %c: integer overflow in format string", code); \ + RETURN_FALSE; \ + } \ + outputpos += (a)*(b); + /* Whether machine is little endian */ char machine_little_endian; @@ -229,7 +236,7 @@ switch ((int) code) { case 'h': case 'H': - outputpos += (arg + 1) / 2; /* 4 bit per arg */ + INC_OUTPUTPOS((arg + 1) / 2,1) /* 4 bit per arg */ break; case 'a': @@ -237,34 +244,34 @@ case 'c': case 'C': case 'x': - outputpos += arg; /* 8 bit per arg */ + INC_OUTPUTPOS(arg,1) /* 8 bit per arg */ break; case 's': case 'S': case 'n': case 'v': - outputpos += arg * 2; /* 16 bit per arg */ + INC_OUTPUTPOS(arg,2) /* 16 bit per arg */ break; case 'i': case 'I': - outputpos += arg * sizeof(int); + INC_OUTPUTPOS(arg,sizeof(int)) break; case 'l': case 'L': case 'N': case 'V': - outputpos += arg * 4; /* 32 bit per arg */ + INC_OUTPUTPOS(arg,4) /* 32 bit per arg */ break; case 'f': - outputpos += arg * sizeof(float); + INC_OUTPUTPOS(arg,sizeof(float)) break; case 'd': - outputpos += arg * sizeof(double); + INC_OUTPUTPOS(arg,sizeof(double)) break; case 'X': @@ -634,6 +641,11 @@ sprintf(n, "%.*s", namelen, name); } + if (size != 0 && size != -1 && INT_MAX - size + 1 < inputpos) { + php_error(E_WARNING, "Type %c: integer overflow", type); + inputpos = 0; + } + if ((inputpos + size) <= inputlen) { switch ((int) type) { case 'a': @@ -804,6 +816,10 @@ } inputpos += size; + if (inputpos < 0) { + php_error(E_WARNING, "Type %c: outside of string", type); + inputpos = 0; + } } else if (arg < 0) { /* Reached end of input for '*' repeater */ break; diff -Naur php-4.2.2/ext/standard/var_unserializer.c php-4.2.2.openpkg-patched/ext/standard/var_unserializer.c --- php-4.2.2/ext/standard/var_unserializer.c 2002-07-21 15:56:37.000000000 +0300 +++ php-4.2.2.openpkg-patched/ext/standard/var_unserializer.c 2004-12-22 09:46:02.000000000 +0200 @@ -62,7 +62,7 @@ if (!var_hash) return !SUCCESS; - if (id >= var_hash->used_slots) return !SUCCESS; + if (id < 0 || id >= var_hash->used_slots) return !SUCCESS; *store = &var_hash->data[id]; @@ -133,7 +133,7 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, int elements) { while (elements-- > 0) { - zval *key, *data; + zval *key, *data, *old_data; ALLOC_INIT_ZVAL(key); @@ -155,9 +155,15 @@ switch (Z_TYPE_P(key)) { case IS_LONG: + if (zend_hash_index_find(ht, Z_LVAL_P(key), (void **)&old_data)) { + var_replace(var_hash, old_data, rval); + } zend_hash_index_update(ht, Z_LVAL_P(key), &data, sizeof(data), NULL); break; case IS_STRING: + if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)) { + var_replace(var_hash, old_data, rval); + } zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, sizeof(data), NULL); break; @@ -424,20 +430,18 @@ zend_error(E_WARNING, "'unserialize_callback_func' (%s) hasn't defined the class it was called for", user_func->value.str.val); incomplete_class = 1; ce = PHP_IC_ENTRY; - } else - efree(class_name); + } } } - } else - efree(class_name); + } *p = YYCURSOR; elements = object_common1(UNSERIALIZE_PASSTHRU, ce); if (incomplete_class) { php_store_class_name(*rval, class_name, len2); - efree(class_name); } + efree(class_name); return object_common2(UNSERIALIZE_PASSTHRU, elements); } diff -Naur php-4.2.2/main/php.h php-4.2.2.openpkg-patched/main/php.h --- php-4.2.2/main/php.h 2002-03-01 02:16:58.000000000 +0200 +++ php-4.2.2.openpkg-patched/main/php.h 2004-12-22 09:03:06.000000000 +0200 @@ -189,6 +189,14 @@ #define LONG_MIN (- LONG_MAX - 1) #endif +#ifndef INT_MAX +#define INT_MAX 2147483647 +#endif + +#ifndef INT_MIN +#define INT_MIN (- INT_MAX - 1) +#endif + #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) || defined(BROKEN_SPRINTF) || defined(BROKEN_SNPRINTF) || defined(BROKEN_VSNPRINTF) #include "snprintf.h" #endif diff -Naur php-4.2.2/main/rfc1867.c php-4.2.2.openpkg-patched/main/rfc1867.c --- php-4.2.2/main/rfc1867.c 2004-12-22 09:53:12.000000000 +0200 +++ php-4.2.2.openpkg-patched/main/rfc1867.c 2004-12-22 09:25:40.000000000 +0200 @@ -57,6 +57,7 @@ #define UPLOAD_ERROR_C 3 /* Only partiallly uploaded */ #define UPLOAD_ERROR_D 4 /* No file uploaded */ #define UPLOAD_ERROR_E 5 /* Uploaded file size 0 bytes */ +#define UPLOAD_ERROR_F 6 /* Missing /tmp or similar directory */ static void add_protected_variable(char *varname TSRMLS_DC) { @@ -740,16 +741,16 @@ SAFE_RETURN; } + total_bytes = cancel_upload = 0; + + /* sec patch: no need to port forward skip_upload because it's never actually used */ /* Handle file */ fp = php_open_temporary_file(PG(upload_tmp_dir), "php", &temp_filename TSRMLS_CC); if (!fp) { sapi_module.sapi_error(E_WARNING, "File upload error - unable to create a temporary file"); - SAFE_RETURN; + cancel_upload = UPLOAD_ERROR_F; } - total_bytes = 0; - cancel_upload = 0; - if(strlen(filename) == 0) { #ifdef DEBUG_FILE_UPLOAD sapi_module.sapi_error(E_NOTICE, "No file uploaded"); @@ -776,10 +777,12 @@ } } } - fclose(fp); + if (fp) { + fclose(fp); + } #ifdef DEBUG_FILE_UPLOAD - if(strlen(filename) > 0 && total_bytes == 0) { + if(strlen(filename) > 0 && total_bytes == 0 && !cancel_upload) { sapi_module.sapi_error(E_WARNING, "Uploaded file size 0 - file [%s=%s] not saved", param, filename); cancel_upload = UPLOAD_ERROR_E; } @@ -787,7 +790,9 @@ if (cancel_upload) { if (temp_filename) { - unlink(temp_filename); + if (cancel_upload != UPLOAD_ERROR_F) { /* file creation failed */ + unlink(temp_filename); + } efree(temp_filename); } temp_filename=""; @@ -825,6 +830,15 @@ } s = strrchr(filename, '\\'); + + if (PG(magic_quotes_gpc)) { + char *tmp; + s = s ? s : filename; + tmp = strrchr(s, '\''); + s = tmp > s ? tmp : s; + tmp = strrchr(s, '"'); + s = tmp > s ? tmp : s; + } if (s && s > filename) { safe_php_register_variable(lbuf, s+1, NULL, 0 TSRMLS_CC); } else { diff -Naur php-4.2.2/main/safe_mode.c php-4.2.2.openpkg-patched/main/safe_mode.c --- php-4.2.2/main/safe_mode.c 2002-03-20 11:02:54.000000000 +0200 +++ php-4.2.2.openpkg-patched/main/safe_mode.c 2004-12-22 09:06:09.000000000 +0200 @@ -49,12 +49,17 @@ int ret, nofile=0; long uid=0L, gid=0L, duid=0L, dgid=0L; char path[MAXPATHLEN]; - char *s; + char *s, *filenamecopy; TSRMLS_FETCH(); if (!filename) { return 0; /* path must be provided */ } + + if (strlcpy(filenamecopy, filename, MAXPATHLEN)>=MAXPATHLEN) { + return 0; + } + filename=(char *)&filenamecopy; if (fopen_mode) { if (fopen_mode[0] == 'r') { diff -Naur php-4.2.2/TSRM/tsrm_virtual_cwd.c php-4.2.2.openpkg-patched/TSRM/tsrm_virtual_cwd.c --- php-4.2.2/TSRM/tsrm_virtual_cwd.c 2002-04-25 17:52:46.000000000 +0300 +++ php-4.2.2.openpkg-patched/TSRM/tsrm_virtual_cwd.c 2004-12-22 09:31:45.000000000 +0200 @@ -273,9 +273,12 @@ if (path_length == 0) return (0); + if (path_length >= MAXPATHLEN) + return (1); #if !defined(TSRM_WIN32) && !defined(__BEOS__) if (IS_ABSOLUTE_PATH(path, path_length)) { + /* use_realpath always on in this version..? */ if (realpath(path, resolved_path)) { path = resolved_path; path_length = strlen(path); @@ -294,6 +297,11 @@ memcpy(ptr, path, path_length); ptr += path_length; *ptr = '\0'; + if (strlen(tmp) >= MAXPATHLEN) { + free(tmp); + return 1; + } + /* realpath always used in this version ..? */ if (realpath(tmp, resolved_path)) { path = resolved_path; path_length = strlen(path); @@ -702,13 +710,24 @@ CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC) { int command_length; + int dir_length, extra = 0; char *command_line; - char *ptr; + char *ptr, *dir; FILE *retval; command_length = strlen(command); - ptr = command_line = (char *) malloc(command_length + sizeof("cd ; ") + CWDG(cwd).cwd_length+1); + dir_length = CWDG(cwd).cwd_length; + dir = CWDG(cwd).cwd; + while (dir_length > 0) { + if (*dir == '\'') extra+=3; + dir++; + dir_length--; + } + dir_length = CWDG(cwd).cwd_length; + dir = CWDG(cwd).cwd; + + ptr = command_line = (char *) malloc(command_length + sizeof("cd '' ; ") + dir_length +1+1); if (!command_line) { return NULL; } @@ -718,8 +737,21 @@ if (CWDG(cwd).cwd_length == 0) { *ptr++ = DEFAULT_SLASH; } else { - memcpy(ptr, CWDG(cwd).cwd, CWDG(cwd).cwd_length); - ptr += CWDG(cwd).cwd_length; + *ptr++ = '\''; + while (dir_length > 0) { + switch (*dir) { + case '\'': + *ptr++ = '\''; + *ptr++ = '\\'; + *ptr++ = '\''; + /* fall-through */ + default: + *ptr++ = *dir; + } + dir++; + dir_length--; + } + *ptr++ = '\''; } *ptr++ = ' ';