Pregunta

I'm trying to get this code: http://code.google.com/p/switchcontrol/source/browse/trunk/code/AFSwitchControl.m compiling under Apple LLVM in Xcode 4.5.2. It works when compiled with LLVM/GCC, but crashes in the mouseDown method when switched to Apple LLVM on line 198:

NSRect knobRect = _AFSwitchControlKnobRectForInsetBackground(slotRect, _offset);

Because _offset is not set. It's suppose to be set in the bind method with this line:

[self setOffset:(CGFloat)[self state]];

But it appears that nothing is being set under LLVM for some reason. My binding call looks like:

[control bind:NSValueBinding toObject:self withKeyPath:@"isToggleSwitchOn" options:nil];

Any ideas why the control's state is not returning anything under LLVM? Thanks!

¿Fue útil?

Solución

The problem is actually a few lines above, in the call to _AFSwitchControlPartRects.

- (void)mouseDown:(NSEvent *)event {
    NSRect textRect, backgroundRect;
    _AFSwitchControlPartRects([self bounds], &textRect, &backgroundRect);

    NSRect slotRect = _AFSwitchControlInsetBackgroundRect(backgroundRect);
    NSRect knobRect = _AFSwitchControlKnobRectForInsetBackground(slotRect, _offset);

The second argument to _AFSwitchControlPartRects, &textRect is a pointer to a rect.

However in the implementation of the function, that parameter is supposed to be a pointer to enough space for two rects.

NS_INLINE void _AFSwitchControlPartRects(NSRect bounds, NSRect *textRects, NSRect *backgroundRect) {
    NSDivideRect(bounds, textRects, backgroundRect, NSWidth(bounds)/5.0, NSMinXEdge);

    textRects[1] = _AFSwitchControlInsetTextRect(NSOffsetRect(textRects[0], NSWidth(*backgroundRect), 0));
    textRects[0] = _AFSwitchControlInsetTextRect(textRects[0]);

When this writes to textRects[1], it's scribbling on -mouseDown's stack. Buffer overflow.

It looks to me like it's happening to clobber self, so the next dereference of self will die. This happens to be the use of _offset.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top