|
22 | 22 |
|
23 | 23 | #include "ext/standard/md5.h"
|
24 | 24 | #include "zend_virtual_cwd.h"
|
| 25 | +#include "main/php_open_temporary_file.h" |
25 | 26 |
|
26 | 27 | #include <sys/types.h>
|
27 | 28 | #include <sys/stat.h>
|
@@ -1536,7 +1537,7 @@ static HashTable* sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *ty
|
1536 | 1537 | return ht;
|
1537 | 1538 | }
|
1538 | 1539 |
|
1539 |
| -static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t, time_t *cached) |
| 1540 | +static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, size_t uri_len, time_t t, time_t *cached) |
1540 | 1541 | {
|
1541 | 1542 | sdlPtr sdl;
|
1542 | 1543 | time_t old_t;
|
@@ -1583,7 +1584,7 @@ static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, time_t t, time
|
1583 | 1584 | *cached = old_t;
|
1584 | 1585 |
|
1585 | 1586 | WSDL_CACHE_GET_INT(i, &in);
|
1586 |
| - if (i == 0 && strncmp(in, uri, i) != 0) { |
| 1587 | + if (i != uri_len || strncmp(in, uri, i) != 0) { |
1587 | 1588 | unlink(fn);
|
1588 | 1589 | efree(buf);
|
1589 | 1590 | return NULL;
|
@@ -2119,7 +2120,10 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s
|
2119 | 2120 | HashTable tmp_bindings;
|
2120 | 2121 | HashTable tmp_functions;
|
2121 | 2122 |
|
2122 |
| - f = open(fn,O_CREAT|O_WRONLY|O_EXCL|O_BINARY,S_IREAD|S_IWRITE); |
| 2123 | + /* To avoid race conditions, we first create a temporary file and then rename it atomically |
| 2124 | + * at the end of the function. (see bug #66150) */ |
| 2125 | + zend_string *temp_file_path; |
| 2126 | + f = php_open_temporary_fd_ex(SOAP_GLOBAL(cache_dir), "tmp.wsdl.", &temp_file_path, PHP_TMP_FILE_SILENT); |
2123 | 2127 |
|
2124 | 2128 | if (f < 0) {return;}
|
2125 | 2129 |
|
@@ -2371,13 +2375,21 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s
|
2371 | 2375 | } ZEND_HASH_FOREACH_END();
|
2372 | 2376 | }
|
2373 | 2377 |
|
2374 |
| - php_ignore_value(write(f, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s))); |
| 2378 | + bool valid_file = write(f, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s)) == ZSTR_LEN(buf.s); |
2375 | 2379 | close(f);
|
| 2380 | + |
| 2381 | + /* Make sure that incomplete files (e.g. due to disk space issues, see bug #66150) are not utilised. */ |
| 2382 | + if (valid_file) { |
| 2383 | + /* This is allowed to fail, this means that another process was raced to create the file. */ |
| 2384 | + (void) VCWD_RENAME(ZSTR_VAL(temp_file_path), fn); |
| 2385 | + } |
| 2386 | + |
2376 | 2387 | smart_str_free(&buf);
|
2377 | 2388 | zend_hash_destroy(&tmp_functions);
|
2378 | 2389 | zend_hash_destroy(&tmp_bindings);
|
2379 | 2390 | zend_hash_destroy(&tmp_encoders);
|
2380 | 2391 | zend_hash_destroy(&tmp_types);
|
| 2392 | + zend_string_release_ex(temp_file_path, false); |
2381 | 2393 | }
|
2382 | 2394 |
|
2383 | 2395 |
|
@@ -3232,7 +3244,7 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_long cache_wsdl)
|
3232 | 3244 | }
|
3233 | 3245 | memcpy(key+len,md5str,sizeof(md5str));
|
3234 | 3246 |
|
3235 |
| - if ((sdl = get_sdl_from_cache(key, uri, t-SOAP_GLOBAL(cache_ttl), &cached)) != NULL) { |
| 3247 | + if ((sdl = get_sdl_from_cache(key, uri, uri_len, t-SOAP_GLOBAL(cache_ttl), &cached)) != NULL) { |
3236 | 3248 | t = cached;
|
3237 | 3249 | efree(key);
|
3238 | 3250 | goto cache_in_memory;
|
|
0 commit comments