Fix GH-10755: Memory leak in phar_rename_archive()#10856
Fix GH-10755: Memory leak in phar_rename_archive()#10856stkeke wants to merge 3 commits intophp:PHP-8.1from stkeke:Fix-GH10755-PHP8.1
Conversation
stkeke
commented
Mar 15, 2023
In phar_renmae_archive() context, added one reference but immediately destroyed another, so do not need to increase refcount. With removal of refcount++ line, PHP/Zend no longer reports memory leak. Updated bug69958.phpt test file accordingly. Testing (PASS on both Debug and Release build) Debug: ./configure --enable-debug Release: ./configure 1) Running selected tests. PASS Phar: bug #69958: Segfault in Phar::convertToData on invalid file [bug69958.phpt] 2) All tests under ext/phar/tests PASSED except skipped. ===================================================================== Number of tests : 530 515 Tests skipped : 15 ( 2.8%) -------- Tests warned : 0 ( 0.0%) ( 0.0%) Tests failed : 0 ( 0.0%) ( 0.0%) Tests passed : 515 ( 97.2%) (100.0%) --------------------------------------------------------------------- Time taken : 26 seconds ===================================================================== Signed-off-by: Su, Tao <tao.su@intel.com>
According to Niels Dossche, remove slash character (/) in bug69958.php test file in order to support testing on both Linux and Windows. Link: #10848 Signed-off-by: Tony Su <tao.su@intel.com>
iluuu1994
left a comment
There was a problem hiding this comment.
ASAN reveals an incorrect free here for phar->alias. Duplicating apparently causes leaks in other places. I don't really know the solution. Do you want to take a closer look or should I?
|
@iluuu1994 If you can take a closer look, that would be wonderful. |
|
@stkeke Did you also pass the |
|
@iluuu1994 I now can reproduce and debug this issue with --asan flag. Thanks for instructing. |
|
This is what I got today... @nielsdos told me pemalloc/pefree should be paired.
|
diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
index ba47cd8843..fbf454e499 100644
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@ -2113,10 +2113,12 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /*
pphar->flags = phar->flags;
pphar->fp = phar->fp;
phar->fp = NULL;
+ phar->alias = NULL;
phar_destroy_phar_data(phar);
*sphar = NULL;
phar = pphar;
- phar->refcount++;
+ /* FIX: GH-10755 Memory leak in phar_rename_archive() */
+ /* phar->refcount++; */
newpath = oldpath;
goto its_ok;
}I think this might do it. Setting |
|
@iluuu1994 Thanks for the hint. Let me check and test it tomorrow. |
|
@iluuu1994 I still need one more day to understand the code logic Only one thing I am not sure, someone (include me) might have a concern that I am wondering, could we do? pphar->fp = phar->fp;
phar->fp = NULL;
+ pphar->alias = phar->alias; /* transfer alias to pphar just as fp */
+ phar->alias = NULL; /* fix double-free issue caught by ASAN */ |
|
@stkeke Of course, sorry, that line was missing in my example. I really don't know how this code works (I've looked at it only superficially) but from looking at how the other properties are handled here that seems to make sense. |
|
@iluuu1994 I traced the So your fixation is quite correct. Let's use it to avoid the first-time release and let it go in destructor. How
|
After having fixed memory leak, ASAN check reported double-free of phar->alias (char*) string. We found the root cause and documented it at #10856 Solution is provided by Ilija Tovilo (iluuu1994). Signed-off-by: Tony Su <tao.su@intel.com> Reviewed-by: Ilija Tovilo Tested-by: Tony Su <tao.su@intel.com>
| phar = pphar; | ||
| phar->refcount++; | ||
| /* FIX: GH-10755 Memory leak in phar_rename_archive() */ | ||
| /* phar->refcount++; */ |
There was a problem hiding this comment.
Sure, no problem. You can simple change it.