Question

I came across a weird issue when testing my opensource project MHTextSearch. At line 169 of MHTextIndex.m:

uint64_t maxLength = [indexedString maximumLengthOfBytesUsingEncoding:encoding];
// some code

for (...) {

    [indexedString getBytes:keyPtr
                  maxLength:maxLength
                 usedLength:&usedLength
                   encoding:encoding
                    options:NSStringEncodingConversionAllowLossy
                      range:subRange
             remainingRange:NULL];

    // some more code
}

Nothing, anywhere else, modifies maxLength. On the second iteration, maxLength is equal to 0, no matter what its previous value was. If I set a watchpoint on it, I see it changes in -[NSString getBytes:maxLength:usedLength:encoding:options:range:remainingRange:], at

0x100038d19:  movq   -0x30(%rbp), %rdx
0x100038d1d:  movq   %rdx, (%rsi)
0x100038d20:  testq  %rcx, %rcx            << this instruction

The very weird thing about this is that it only happens on the x86_64 architecture, and it can be fixed if I change the code like this

uint64_t maxLength = [indexedString maximumLengthOfBytesUsingEncoding:encoding];
uint64_t strLength = maxLength;
// some code

for (...) {

    [indexedString getBytes:keyPtr
                  maxLength:strLength
                 usedLength:&usedLength
                   encoding:encoding
                    options:NSStringEncodingConversionAllowLossy
                      range:subRange
             remainingRange:NULL];

    // some more code
}

With this code, maxLength still gets changed to 0 at the same instruction, but strLength stays consistent, so the effect is removed.

How come?

Was it helpful?

Solution

usedLength has the wrong type. It's declared uint32_t. However, it should be declared NSUInteger, which is 32 bits on 32 bit architectures and 64 bits on 64 bit architectures.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top