
I was working on pulling library calling code from JRegex into Text.Regex.Lazy and I am wondering if this code for compiling regex.h regular expressions is a potential memory leak:
regcomp pattern flags = do regex_fptr <- mallocForeignPtrBytes (#const sizeof(regex_t)) r <- withCString pattern $ \cstr -> withForeignPtr regex_fptr $ \p -> c_regcomp p cstr (fromIntegral flags) if (r == 0) then do addForeignPtrFinalizer ptr_regfree regex_fptr return (Regex regex_fptr) else error "Text.Regex.Posix.regcomp: error in pattern" -- ToDo
The (r/=0) path calls error, but never attaches the finalizer. And the man page for regex says:
The regfree() function frees any dynamically-allocated storage associated with the compiled RE pointed to by preg. The remaining regex_t is no longer a valid compiled RE and the effect of supplying it to regexec() or regerror() is undefined.
So it looks like the c_regcomp might allocate memory associated with regex_fptr even in the event of an error, so this case needs the same finalizer. I have not re-compiled GHC, but I have attached a small untested patch to change the code to always trigger the finalizer when there is an error:
regcomp pattern flags = do regex_fptr <- mallocForeignPtrBytes (#const sizeof(regex_t)) addForeignPtrFinalizer ptr_regfree regex_fptr r <- withCString pattern $ \cstr -> withForeignPtr regex_fptr $ \p -> c_regcomp p cstr (fromIntegral flags) if (r == 0) then return (Regex regex_fptr) else do finalizeForeignPtr regex_fptr error "Text.Regex.Posix.regcomp: error in pattern" -- ToDo
Cheers, Chris --- Text/Regex/Posix-orig.hsc 2006-07-18 11:06:55.000000000 +0100 +++ Text/Regex/Posix.hsc 2006-07-18 11:18:57.000000000 +0100 @@ -79,13 +79,14 @@ -> IO Regex -- ^ Returns: the compiled regular expression regcomp pattern flags = do regex_fptr <- mallocForeignPtrBytes (#const sizeof(regex_t)) + addForeignPtrFinalizer ptr_regfree regex_fptr r <- withCString pattern $ \cstr -> withForeignPtr regex_fptr $ \p -> c_regcomp p cstr (fromIntegral flags) if (r == 0) - then do addForeignPtrFinalizer ptr_regfree regex_fptr - return (Regex regex_fptr) - else error "Text.Regex.Posix.regcomp: error in pattern" -- ToDo + then return (Regex regex_fptr) + else do finalizeForeignPtr regex_fptr + error "Text.Regex.Posix.regcomp: error in pattern" -- ToDo -- ----------------------------------------------------------------------------- -- regexec