mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-06 14:05:32 +00:00
ICU-21662 UVector Error Handling in Regex
Clean up some oversights from commit0ec329c
. This was triggered by fuzz testing finding a memory leak with the original commit, see https://oss-fuzz.com/testcase-detail/4656781834452992 I was unable to replicate the fuzzing failure, but reviewing the nearby code showed some likely problems. In this commit, - Fix UStack::pop() to not delete the popped element when a deleter function is present. This was a bug, but because there were no stacks with deleters, was not causing trouble. - Change RegexCompile::compileSet() to delete the set if it cannot be added to the internal vector of sets. I suspect this is the cause of the fuzzing leak -0ec329c
changed the behavior of UVector in the presence of errors. - Changed RegexCompile::fSetStack to use an object deleter function. This fixes the leak checking at the points new elements are pushed onto this stack.
This commit is contained in:
parent
e69f337f3c
commit
46861a5c78
3 changed files with 13 additions and 10 deletions
|
@ -37,10 +37,9 @@ UStack::~UStack() {}
|
|||
|
||||
void* UStack::pop(void) {
|
||||
int32_t n = size() - 1;
|
||||
void* result = 0;
|
||||
void* result = nullptr;
|
||||
if (n >= 0) {
|
||||
result = elementAt(n);
|
||||
removeElementAt(n);
|
||||
result = orphanElementAt(n);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -346,6 +346,11 @@ public:
|
|||
|
||||
inline int32_t peeki(void) const {return lastElementi();}
|
||||
|
||||
/**
|
||||
* Pop and return an element from the stack.
|
||||
* For stacks with a deleter function, the caller takes ownership
|
||||
* of the popped element.
|
||||
*/
|
||||
void* pop(void);
|
||||
|
||||
int32_t popi(void);
|
||||
|
|
|
@ -53,7 +53,7 @@ U_NAMESPACE_BEGIN
|
|||
//
|
||||
//------------------------------------------------------------------------------
|
||||
RegexCompile::RegexCompile(RegexPattern *rxp, UErrorCode &status) :
|
||||
fParenStack(status), fSetStack(status), fSetOpStack(status)
|
||||
fParenStack(status), fSetStack(uprv_deleteUObject, nullptr, status), fSetOpStack(status)
|
||||
{
|
||||
// Lazy init of all shared global sets (needed for init()'s empty text)
|
||||
RegexStaticSets::initGlobals(&status);
|
||||
|
@ -278,11 +278,6 @@ void RegexCompile::compile(
|
|||
|
||||
if (U_FAILURE(*fStatus)) {
|
||||
// Bail out if the pattern had errors.
|
||||
// Set stack cleanup: a successful compile would have left it empty,
|
||||
// but errors can leave temporary sets hanging around.
|
||||
while (!fSetStack.empty()) {
|
||||
delete (UnicodeSet *)fSetStack.pop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2431,7 +2426,11 @@ void RegexCompile::compileSet(UnicodeSet *theSet)
|
|||
theSet->freeze();
|
||||
int32_t setNumber = fRXPat->fSets->size();
|
||||
fRXPat->fSets->addElement(theSet, *fStatus);
|
||||
appendOp(URX_SETREF, setNumber);
|
||||
if (U_SUCCESS(*fStatus)) {
|
||||
appendOp(URX_SETREF, setNumber);
|
||||
} else {
|
||||
delete theSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue