[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: libs-corebase: NS/CFNumber bridging crashes with small objects
From: |
David Chisnall |
Subject: |
Re: libs-corebase: NS/CFNumber bridging crashes with small objects |
Date: |
Fri, 8 Nov 2019 12:57:41 +0000 |
User-agent: |
Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.9.0 |
Hi,
There are a few different representations of numbers in the small object
representation. On 32-bit platforms, there is only small int, which has
the low bit set to 1 and stores a 32-bit integer in the remaining bits.
On 64-bit platforms, the low 3 bits indicate the type, with the
following values:
0: Object pointer
1: Small int (61-bit integer)
2: Small extended double (64-bit double, where the low bits of the
mantissa are represented)
3: Small repeating double (64-bit double where the low bits are a short
repeated pattern.
4: Unused
5: Tiny string (8 7-bit ASCI characters, plus length).
6: Unused
7: Unused
The numerical representations are defined in NSNumber:
https://github.com/gnustep/libs-base/blob/280b2cbe834007fa7945d783f3a538ecbaab52b5/Source/NSNumber.m#L374
https://github.com/gnustep/libs-base/blob/280b2cbe834007fa7945d783f3a538ecbaab52b5/Source/NSNumber.m#L436
The tiny string representation is defined in GSString.m:
https://github.com/gnustep/libs-base/blob/dd368559230c485b1234695673f21b2269caca09/Source/GSString.m#L778
Note that, with the 2.0 ABI, the GSTinyString representation is emitted
by the compiler and so are considered part of the stable ABI. The other
number representations are not and are considered internal to the -base
implementation and may change between versions. I believe CoreBase is
version locked to base, so that isn't a problem.
The code in CoreBase will need updating to check for the small number
representation. I'd be inclined to do this by moving some of the code
from NSNumber.m and GSString.m into a private header that can be shared
between base and CoreBase.
David
On 08/11/2019 11:18, Frederik Seiffert wrote:
Hi all,
I found that toll-free bridging of NSNumber to CFNumber crashes when
using a "small object" (aka tagged pointer):
NSNumber *num = @(42);
NSLog(@"Type: %ld", (long)CFNumberGetType((__bridge CFNumberRef)num));
Crashes like this:
* thread #1: tid = 27602, 0x00007fe328027ba0
libgnustep-corebase.so.0`CFNumberGetType
[inlined] CFNumberGetType_internal(num=0x0000000000000151) at
CFNumber.c:204, name = 'test', stop reason = invalid address (fault
address: 0x15b)
frame #0: 0x00007fe328027ba0
libgnustep-corebase.so.0`CFNumberGetType
[inlined] CFNumberGetType_internal(num=0x0000000000000151) at CFNumber.c:204
201 CF_INLINE CFNumberType
202 CFNumberGetType_internal(CFNumberRef num)
203 {
-> 204 return (CFNumberType)num->_parent._flags.info <http://flags.info>;
205 }
206
207 CF_INLINE CFIndex
Note that 0x151 is a small int object for 42. Replacing 42 with e.g.
INT_MAX (which doesn’t fit in a small object) makes the code work fine.
Could anyone with knowledge of the corebase / small objects internals
take a look at this, or point me in the right direction how to fix this?
Related, there currently doesn’t seem to be a way to report bugs on
corebase. Would it be possible to enable the bugtracker for the corebase
GitHub project?
Thanks!
Frederik