Skip to content

Commit f3380b6

Browse files
committed
Fix phpGH-20679: finfo_file() doesn't work on remote resources
WIP
1 parent fa15b7e commit f3380b6

File tree

3 files changed

+46
-26
lines changed

3 files changed

+46
-26
lines changed

ext/fileinfo/fileinfo.c

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -242,16 +242,8 @@ static const char* php_fileinfo_from_path(struct magic_set *magic, const zend_st
242242
ZEND_ASSERT(!zend_str_has_nul_byte(path));
243243
ZEND_ASSERT(context != NULL);
244244

245-
/* determine if the file is a local file or remote URL */
246-
const char *dummy;
247-
php_stream_statbuf ssb;
248-
249-
const php_stream_wrapper *wrap = php_stream_locate_url_wrapper(ZSTR_VAL(path), &dummy, 0);
250-
if (UNEXPECTED(wrap == NULL)) {
251-
return NULL;
252-
}
253-
254245
#ifdef PHP_WIN32
246+
php_stream_statbuf ssb;
255247
if (php_stream_stat_path_ex(ZSTR_VAL(path), 0, &ssb, context) == SUCCESS) {
256248
if (ssb.sb.st_mode & S_IFDIR) {
257249
return "directory";
@@ -264,16 +256,9 @@ static const char* php_fileinfo_from_path(struct magic_set *magic, const zend_st
264256
return NULL;
265257
}
266258

267-
const char *ret_val = NULL;
268-
if (php_stream_stat(stream, &ssb) == SUCCESS) {
269-
if (ssb.sb.st_mode & S_IFDIR) {
270-
ret_val = "directory";
271-
} else {
272-
ret_val = magic_stream(magic, stream);
273-
if (UNEXPECTED(ret_val == NULL)) {
274-
php_error_docref(NULL, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic));
275-
}
276-
}
259+
const char *ret_val = magic_stream(magic, stream);
260+
if (UNEXPECTED(ret_val == NULL)) {
261+
php_error_docref(NULL, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic));
277262
}
278263

279264
php_stream_close(stream);

ext/fileinfo/libmagic/magic.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ magic_stream(struct magic_set *ms, php_stream *stream)
195195
file_private const char *
196196
file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
197197
{
198-
int rv = -1;
198+
const char *ret = NULL;
199199
unsigned char *buf;
200200
zend_stat_t sb = {0};
201201
ssize_t nbytes = 0; /* number of bytes read from a datafile */
@@ -218,7 +218,7 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
218218
case 0: /* nothing found */
219219
break;
220220
default: /* matched it and printed type */
221-
rv = 0;
221+
ret = file_getbuffer(ms);
222222
goto done;
223223
}
224224

@@ -230,7 +230,6 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
230230
if (!stream) {
231231
if (unreadable_info(ms, sb.st_mode, inname) == -1)
232232
goto done;
233-
rv = -1;
234233
goto done;
235234
}
236235
}
@@ -239,7 +238,6 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
239238
if (php_stream_stat(stream, &ssb) < 0) {
240239
if (ms->flags & MAGIC_ERROR) {
241240
file_error(ms, errno, "cannot stat `%s'", inname);
242-
rv = -1;
243241
goto done;
244242
}
245243
}
@@ -248,23 +246,34 @@ file_or_stream(struct magic_set *ms, const char *inname, php_stream *stream)
248246
/*
249247
* try looking at the first ms->bytes_max bytes
250248
*/
249+
zend_begin_record_errors();
251250
if ((nbytes = php_stream_read(stream, (char *)buf, ms->bytes_max - nbytes)) < 0) {
252-
file_error(ms, errno, "cannot read `%s'", inname);
251+
if (errno == EISDIR) {
252+
EG(record_errors) = false;
253+
ret = "directory";
254+
} else {
255+
zend_emit_recorded_errors();
256+
file_error(ms, errno, "cannot read `%s'", inname);
257+
}
258+
zend_free_recorded_errors();
253259
goto done;
254260
}
261+
zend_emit_recorded_errors();
262+
zend_free_recorded_errors();
255263

256264
(void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
257265
if (file_buffer(ms, stream, &sb, inname, buf, CAST(size_t, nbytes)) == -1)
258266
goto done;
259-
rv = 0;
267+
ret = file_getbuffer(ms);
268+
260269
done:
261270
efree(buf);
262271

263272
if (no_in_stream && stream) {
264273
php_stream_close(stream);
265274
}
266275
out:
267-
return rv == 0 ? file_getbuffer(ms) : NULL;
276+
return ret;
268277
}
269278

270279

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
GH-20679 (finfo_file() doesn't work on remote resources)
3+
--EXTENSIONS--
4+
fileinfo
5+
--INI--
6+
allow_url_fopen=1
7+
--SKIPIF--
8+
<?php
9+
if (@!include "./ext/standard/tests/http/server.inc") die('skip server.inc not available');
10+
http_server_skipif();
11+
?>
12+
--FILE--
13+
<?php
14+
require "./ext/standard/tests/http/server.inc";
15+
16+
['pid' => $pid, 'uri' => $uri] = http_server([
17+
"data://text/plain,HTTP/1.0 200 Ok\r\n\r\n<html>foo",
18+
], $output);
19+
20+
$f = finfo_open();
21+
var_dump(finfo_file($f, $uri));
22+
23+
http_server_kill($pid);
24+
?>
25+
--EXPECT--
26+
string(51) "HTML document, ASCII text, with no line terminators"

0 commit comments

Comments
 (0)