Crash in CFRegularExpressionCreate


(Pushkar N Kulkarni) #1

Hi Philippe, other interested folks:

This code that tries to create an NSRegularExpression out of an invalid pattern will crash due to a HALT:

do {

let re = try NSRegularExpression(pattern: “\”, options: [])

} catch {

print(“uh oh”)

}

I dug around CoreFoundation and have the following failure hypothesis:

  1. In CFRegularExpressionCreate when uregex_open() returns an error, we construct a CFDictionary for the CFError, like this:

                 *CFStringRef keys[] = {CFSTR("NSInvalidValue”)};*
    
  •                CFTypeRef values[] = {pattern};*
    

_ CFDictionaryRef userInfo = CFDictionaryCreate(kCFAllocatorSystemDefault, (const void **)keys, (const void **)values, …….)_

  1. In CFDictionaryCreate( ) each key-value pair is added via the CFAddBasicHashValue( ) function, which eventually tries to calculate the hash of the key.

  2. The hash of the key is calculated like this (all of this is done in CFHash() in CFRuntime.c):

3.1) extract the typeID from the key

3.2) using the typeID as an index into the CFRuntimeClassTable, get the related CFRuntimeClass ©

3.3) get the has function pointer c->hash

3.4) invoke the hash function

  1. Now going back to (1), the key here is a CFString returned by CFSTR(). This instance is NOT created using the _CFRuntimeCreateInstance() function

and hence it does not embed a typeID (the typeID will be 0).

  1. Applying the sequence in (3) to a CFString returned by CFSTR() yields:

3.1) typeID = 0

3.2) index = 0, c = _CFNotATypeClass is present at index = 0

3.3) c->hash = HALT

3.4) we call HALT and hence stop

A validation of the above hypothesis (and a way to work around this is) is by creating the key in (1) this way:

CFStringRef keys[] = { CFStringCreateWithCString(kCFAllocatorSystemDefault, “NSInvalidValue”, kCFStringEncodingUTF8) };

The crash goes away.

I see a lot of places in CoreFoundation where CFString instances returned by CFSTR() are used as keys into a CFDictionary. I would say all of them are potentials points of failure per the above hypothesis.

Do you agree with the failure theory? What do you think we should be doing to fix this?

Pushkar N Kulkarni,

IBM Runtimes

Simplicity is prerequisite for reliability - Edsger W. Dijkstra