3636#include "fopen_wrappers.h" /* needed for is_url */
3737#include "Zend/zend_exceptions.h"
3838
39- /* {{{ macros and type definitions */
40- typedef struct _php_fileinfo {
41- zend_long options ;
42- struct magic_set * magic ;
43- } php_fileinfo ;
44-
4539static zend_object_handlers finfo_object_handlers ;
4640zend_class_entry * finfo_class_entry ;
4741
4842typedef struct _finfo_object {
49- php_fileinfo * ptr ;
43+ struct magic_set * magic ;
5044 zend_object zo ;
5145} finfo_object ;
5246
@@ -56,26 +50,12 @@ static inline finfo_object *php_finfo_fetch_object(zend_object *obj) {
5650
5751#define Z_FINFO_P (zv ) php_finfo_fetch_object(Z_OBJ_P((zv)))
5852
59- #define FILEINFO_FROM_OBJECT (finfo , object ) \
60- { \
61- finfo_object *obj = Z_FINFO_P(object); \
62- finfo = obj->ptr; \
63- if (!finfo) { \
64- zend_throw_error(NULL, "Invalid finfo object"); \
65- RETURN_THROWS(); \
66- } \
67- }
68-
6953/* {{{ finfo_objects_free */
7054static void finfo_objects_free (zend_object * object )
7155{
7256 finfo_object * intern = php_finfo_fetch_object (object );
7357
74- if (intern -> ptr ) {
75- magic_close (intern -> ptr -> magic );
76- efree (intern -> ptr );
77- }
78-
58+ magic_close (intern -> magic );
7959 zend_object_std_dtor (& intern -> zo );
8060}
8161/* }}} */
@@ -153,7 +133,6 @@ PHP_FUNCTION(finfo_open)
153133 zend_long options = MAGIC_NONE ;
154134 char * file = NULL ;
155135 size_t file_len = 0 ;
156- php_fileinfo * finfo ;
157136 zval * object = getThis ();
158137 char resolved_path [MAXPATHLEN ];
159138 zend_error_handling zeh ;
@@ -163,15 +142,10 @@ PHP_FUNCTION(finfo_open)
163142 }
164143
165144 if (object ) {
166- finfo_object * finfo_obj = Z_FINFO_P (object );
167-
168145 zend_replace_error_handling (EH_THROW , NULL , & zeh );
169146
170- if (finfo_obj -> ptr ) {
171- magic_close (finfo_obj -> ptr -> magic );
172- efree (finfo_obj -> ptr );
173- finfo_obj -> ptr = NULL ;
174- }
147+ magic_close (Z_FINFO_P (object )-> magic );
148+ Z_FINFO_P (object )-> magic = NULL ;
175149 }
176150
177151 if (file_len == 0 ) {
@@ -199,13 +173,9 @@ PHP_FUNCTION(finfo_open)
199173 file = resolved_path ;
200174 }
201175
202- finfo = emalloc ( sizeof ( php_fileinfo ) );
176+ struct magic_set * magic = magic_open ( options );
203177
204- finfo -> options = options ;
205- finfo -> magic = magic_open (options );
206-
207- if (finfo -> magic == NULL ) {
208- efree (finfo );
178+ if (magic == NULL ) {
209179 php_error_docref (NULL , E_WARNING , "Invalid mode '" ZEND_LONG_FMT "'." , options );
210180 if (object ) {
211181 zend_restore_error_handling (& zeh );
@@ -216,10 +186,9 @@ PHP_FUNCTION(finfo_open)
216186 RETURN_FALSE ;
217187 }
218188
219- if (magic_load (finfo -> magic , file ) == -1 ) {
189+ if (magic_load (magic , file ) == -1 ) {
220190 php_error_docref (NULL , E_WARNING , "Failed to load magic database at \"%s\"" , file );
221- magic_close (finfo -> magic );
222- efree (finfo );
191+ magic_close (magic );
223192 if (object ) {
224193 zend_restore_error_handling (& zeh );
225194 if (!EG (exception )) {
@@ -230,14 +199,13 @@ PHP_FUNCTION(finfo_open)
230199 }
231200
232201 if (object ) {
233- finfo_object * obj ;
234202 zend_restore_error_handling (& zeh );
235- obj = Z_FINFO_P (object );
236- obj -> ptr = finfo ;
203+ finfo_object * obj = Z_FINFO_P (object );
204+ obj -> magic = magic ;
237205 } else {
238206 zend_object * zobj = finfo_objects_new (finfo_class_entry );
239207 finfo_object * obj = php_finfo_fetch_object (zobj );
240- obj -> ptr = finfo ;
208+ obj -> magic = magic ;
241209 RETURN_OBJ (zobj );
242210 }
243211}
@@ -260,18 +228,20 @@ PHP_FUNCTION(finfo_close)
260228PHP_FUNCTION (finfo_set_flags )
261229{
262230 zend_long options ;
263- php_fileinfo * finfo ;
264231 zval * self ;
265232
266233 if (zend_parse_method_parameters (ZEND_NUM_ARGS (), getThis (), "Ol" , & self , finfo_class_entry , & options ) == FAILURE ) {
267234 RETURN_THROWS ();
268235 }
269- FILEINFO_FROM_OBJECT (finfo , self );
236+
237+ if (!Z_FINFO_P (self )-> magic ) {
238+ zend_throw_error (NULL , "Invalid finfo object" );
239+ RETURN_THROWS ();
240+ }
270241
271242 /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME
272243 * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */
273- magic_setflags (finfo -> magic , options );
274- finfo -> options = options ;
244+ magic_setflags (Z_FINFO_P (self )-> magic , options );
275245
276246 RETURN_TRUE ;
277247}
@@ -331,13 +301,17 @@ PHP_FUNCTION(finfo_file)
331301 zend_string * path = NULL ;
332302 zend_long options = 0 ;
333303 zval * zcontext = NULL ;
334- php_fileinfo * finfo = NULL ;
335304
336305 if (zend_parse_method_parameters (ZEND_NUM_ARGS (), getThis (), "OP|lr!" , & self , finfo_class_entry , & path , & options , & zcontext ) == FAILURE ) {
337306 RETURN_THROWS ();
338307 }
339- FILEINFO_FROM_OBJECT (finfo , self );
340- struct magic_set * magic = finfo -> magic ;
308+
309+ if (!Z_FINFO_P (self )-> magic ) {
310+ zend_throw_error (NULL , "Invalid finfo object" );
311+ RETURN_THROWS ();
312+ }
313+
314+ struct magic_set * magic = Z_FINFO_P (self )-> magic ;
341315
342316 if (UNEXPECTED (ZSTR_LEN (path ) == 0 )) {
343317 zend_argument_must_not_be_empty_error (2 );
@@ -349,16 +323,18 @@ PHP_FUNCTION(finfo_file)
349323 }
350324
351325 /* Set options for the current file/buffer. */
326+ int old_options = magic_getflags (magic );
352327 if (options ) {
353328 /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME
354329 * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */
355330 magic_setflags (magic , options );
356331 }
357332
358333 const char * ret_val = php_fileinfo_from_path (magic , path , context );
334+
359335 /* Restore options */
360336 if (options ) {
361- magic_setflags (magic , finfo -> options );
337+ magic_setflags (magic , old_options );
362338 }
363339
364340 if (UNEXPECTED (ret_val == NULL )) {
@@ -375,24 +351,31 @@ PHP_FUNCTION(finfo_buffer)
375351 zend_string * buffer = NULL ;
376352 zend_long options = 0 ;
377353 zval * dummy_context = NULL ;
378- php_fileinfo * finfo = NULL ;
379354
380355 if (zend_parse_method_parameters (ZEND_NUM_ARGS (), getThis (), "OS|lr!" , & self , finfo_class_entry , & buffer , & options , & dummy_context ) == FAILURE ) {
381356 RETURN_THROWS ();
382357 }
383- FILEINFO_FROM_OBJECT (finfo , self );
384- struct magic_set * magic = finfo -> magic ;
358+
359+ if (!Z_FINFO_P (self )-> magic ) {
360+ zend_throw_error (NULL , "Invalid finfo object" );
361+ RETURN_THROWS ();
362+ }
363+
364+ struct magic_set * magic = Z_FINFO_P (self )-> magic ;
385365
386366 /* Set options for the current file/buffer. */
367+ int old_options = magic_getflags (magic );
387368 if (options ) {
369+ /* We do not check the return value as it can only ever fail if options contains MAGIC_PRESERVE_ATIME
370+ * and the system neither has utime(3) nor utimes(2). Something incredibly unlikely. */
388371 magic_setflags (magic , options );
389372 }
390373
391374 const char * ret_val = magic_buffer (magic , ZSTR_VAL (buffer ), ZSTR_LEN (buffer ));
392375
393376 /* Restore options */
394377 if (options ) {
395- magic_setflags (magic , finfo -> options );
378+ magic_setflags (magic , old_options );
396379 }
397380
398381 if (UNEXPECTED (ret_val == NULL )) {
0 commit comments