From: <mie...@us...> - 2012-08-08 23:22:40
|
Revision: 8170 http://oorexx.svn.sourceforge.net/oorexx/?rev=8170&view=rev Author: miesfeld Date: 2012-08-08 23:22:34 +0000 (Wed, 08 Aug 2012) Log Message: ----------- Fix potential memory problems in the SysFileTree implementation Modified Paths: -------------- main/trunk/extensions/rexxutil/platform/unix/rexxutil.cpp main/trunk/extensions/rexxutil/platform/windows/rexxutil.cpp Modified: main/trunk/extensions/rexxutil/platform/unix/rexxutil.cpp =================================================================== --- main/trunk/extensions/rexxutil/platform/unix/rexxutil.cpp 2012-08-08 22:48:06 UTC (rev 8169) +++ main/trunk/extensions/rexxutil/platform/unix/rexxutil.cpp 2012-08-08 23:22:34 UTC (rev 8170) @@ -3190,6 +3190,15 @@ * * Note that we can count the characters used for both the time data * and attribute data, so we know the buffers are large enough. + * + * If the file search is a very deep recursion in the host file + * system, a very large number of String objects may be created in the + * single Call context of SysFileTree. A reference to each created + * object is saved in a hash table to protect it from garbage + * collection, which can lead to a very large hash table. To prevent + * the creation of a very large hash table, we create a temp object, + * pass that object to the interpreter, and then tell the interpreter + * the object no longer needs to be protected in this call context. */ bool formatFile(RexxCallContext *c, RXTREEDATA *treeData, uint32_t options, struct stat *finfo) { @@ -3283,8 +3292,11 @@ } // Place found file line in the stem. + RexxString Object t = c->String(treeData->foundFileLine); + treeData->count++; - c->SetStemArrayElement(treeData->files, treeData->count, c->String(treeData->foundFileLine)); + c->SetStemArrayElement(treeData->files, treeData->count, t); + c->ReleaseLocalReference(t); return true; } Modified: main/trunk/extensions/rexxutil/platform/windows/rexxutil.cpp =================================================================== --- main/trunk/extensions/rexxutil/platform/windows/rexxutil.cpp 2012-08-08 22:48:06 UTC (rev 8169) +++ main/trunk/extensions/rexxutil/platform/windows/rexxutil.cpp 2012-08-08 23:22:34 UTC (rev 8170) @@ -1850,6 +1850,14 @@ * it of course. We can determine if the memory needs to be freed by checking * that either nFoundFile, or nFoundFileLine, are the same size as they are * originally set to, or not. + * + * If the file search is a very deep recursion in the host file system, a very + * large number of String objects may be created in the single Call context of + * SysFileTree. A reference to each created object is saved in a hash table to + * protect it from garbage collection, which can lead to a very large hash + * table. To prevent the creation of a very large hash table, we create a temp + * object, pass that object to the interpreter, and then tell the interpreter + * the object no longer needs to be protected in this call context. */ static bool formatFile(RexxCallContext *c, char *path, RXTREEDATA *treeData, int32_t *newMask, uint32_t options, WIN32_FIND_DATA *wfd) @@ -1888,9 +1896,12 @@ if ( options & NAME_ONLY ) { + RexxStringObject t = c->String(dFoundFile); + // Add the file name to the stem and be done with it. treeData->count++; - c->SetStemArrayElement(treeData->files, treeData->count, c->String(dFoundFile)); + c->SetStemArrayElement(treeData->files, treeData->count, t); + c->ReleaseLocalReference(t); if ( nFoundFile != sizeof(treeData->foundFile) ) { @@ -1956,7 +1967,6 @@ char *dFoundFileLine = treeData->foundFileLine; size_t nFoundFileLine = sizeof(treeData->foundFileLine); - len = _snprintf(dFoundFileLine, nFoundFileLine, "%s%s%s", treeData->fileTime, treeData->fileAttr, dFoundFile); if ( len < 0 || len == nFoundFileLine ) @@ -1976,8 +1986,11 @@ } // Place found file line in the stem. + RexxStringObject t = c->String(dFoundFileLine); + treeData->count++; - c->SetStemArrayElement(treeData->files, treeData->count, c->String(dFoundFileLine)); + c->SetStemArrayElement(treeData->files, treeData->count, t); + c->ReleaseLocalReference(t); if ( nFoundFile != sizeof(treeData->foundFile) ) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |