The following issue arose during the last few days. On current 64bit Squeak bundles, when setting a morph to an x position being (2 raisedTo: 31) in a world having an InfiniteForm, the VM crashes with a SegFault. This does not happen with (2 raisedTo: 32) or (2 raisedTo: 30).
So far I was able to reproduce this on Windows and Linux (have not checked Mac yet). I tried to boil it down to the BitBlt call that causes this with the second example. At the bottom I have attached an example crash.dmp.
This does not happen on 32bit bundles. It does occur on older 64bit Squeak releases (e.g. 5.2).
```Smalltalk "Execute this in a World with a texture (InfiniteForm) background" m := CircleMorph new openInWorld. m position: (2 raisedTo: 31)@100. ```
```Smalltalk patternForm := Form extent: 3 @ 3 depth: 32. port := GrafPort new. port setDestForm: Display. port sourceForm: sourceForm. port fillColor: nil. port combinationRule: Form paint. port sourceRect: (0@0 extent: patternForm boundingBox extent). port destOrigin: (2 raisedTo: 31)@100. port copyBits. ```
```` /mnt/c/Users/patri/Desktop/swag/teaching/SWA1920/tmp_image/SWA2020Trunk.app/Contents/Linux-x86_64/lib/squeak/5.0-201810190412/squeak Squeak VM version: 5.0-201810190412 Sat Oct 20 08:15:47 UTC 2018 gcc 4.8 [Production Spur 64-bit VM] Built from: CoInterpreter VMMaker.oscog-eem.2461 uuid: b3cd33f5-6309-43a1-b669-7a1805111f34 Oct 20 2018 With: StackToRegisterMappingCogit VMMaker.oscog-eem.2464 uuid: 0b1fa0a3-a781-4fd5-b1cf-1809796ccbbf Oct 20 2018 Revision: VM: 201810190412 https://github.com/OpenSmalltalk/opensmalltalk-vm.git Date: Thu Oct 18 21:12:21 2018 CommitHash: 15341b57 Plugins: 201810190412 https://github.com/OpenSmalltalk/opensmalltalk-vm.git Build host: Linux travis-job-7e855ac8-57b9-4f6f-bf30-fd6e0ad67398 4.4.0-101-generic #124~14.04.1-Ubuntu SMP Fri Nov 10 19:05:36 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux plugin path: Linux-x86_64/lib/squeak/5.0-201810190412 [default: /mnt/c/Users/patri/Desktop/swag/teaching/SWA1920/tmp_image/SWA2020Trunk.app/Contents/Linux-x86_64/lib/squeak/5.0-201810190412/]
C stack backtrace & registers: rax 0xef63a4c0 rbx 0xef63a350 rcx 0xef63a578 rdx 0xef63a408 rdi 0xef63a128 rsi 0xef63a128 rbp 0xef63a298 rsp 0xef63a630 r8 0xef639b68 r9 0xef639c20 r10 0xef639cd8 r11 0xef639d90 r12 0xef639e48 r13 0xef639f00 r14 0xef639fb8 r15 0xef63a070 rip 0xef63a6e8 *[0x7fffef63a6e8] Linux-x86_64/lib/squeak/5.0-201810190412/squeak[0x41b767] Linux-x86_64/lib/squeak/5.0-201810190412/squeak[0x41d1d5] /lib/x86_64-linux-gnu/libpthread.so.0(+0x12890)[0x7f82c2e42890] Linux-x86_64/lib/squeak/5.0-201810190412/squeak[0x4b50c4] Linux-x86_64/lib/squeak/5.0-201810190412/squeak[0x4ba99c] Linux-x86_64/lib/squeak/5.0-201810190412/squeak[0x4baf59] Linux-x86_64/lib/squeak/5.0-201810190412/squeak[0x458cc7] Linux-x86_64/lib/squeak/5.0-201810190412/squeak(interpret+0xa687)[0x468157] Linux-x86_64/lib/squeak/5.0-201810190412/squeak[0x469306] Linux-x86_64/lib/squeak/5.0-201810190412/squeak(interpret+0x246)[0x45dd16] Linux-x86_64/lib/squeak/5.0-201810190412/squeak(main+0x2fa)[0x41ac8a] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x7f82c2a51b97] Linux-x86_64/lib/squeak/5.0-201810190412/squeak[0x41afb4] [0x0]
Smalltalk stack dump: 0x7fffef6963a8 I GrafPort>copyBits 0x26bf808: a(n) GrafPort 0x7fffef6963d8 M UndefinedObject>DoIt 0x29e78e0: a(n) UndefinedObject 0x7fffef696430 I Compiler>evaluateCue:ifFail: 0x26040b0: a(n) Compiler 0x7fffef697dc0 I Compiler>evaluateCue:ifFail:logged: 0x26040b0: a(n) Compiler 0x7fffef697e18 I Compiler>evaluate:in:to:environment:notifying:ifFail:logged: 0x26040b0: a(n) Compiler 0x7fffef697e90 M [] in SmalltalkEditor(TextEditor)>evaluateSelectionAndDo: 0x8864a20: a(n) SmalltalkEditor 0x7fffef697ec8 M BlockClosure>on:do: 0x2604060: a(n) BlockClosure 0x7fffef697f30 I SmalltalkEditor(TextEditor)>evaluateSelectionAndDo: 0x8864a20: a(n) SmalltalkEditor 0x7fffef697f78 I SmalltalkEditor(TextEditor)>evaluateSelection 0x8864a20: a(n) SmalltalkEditor 0x7fffef697fb8 I SmalltalkEditor(TextEditor)>doIt 0x8864a20: a(n) SmalltalkEditor 0x7fffef697fe8 M SmalltalkEditor(TextEditor)>doIt: 0x8864a20: a(n) SmalltalkEditor 0x7fffef698040 I SmalltalkEditor(TextEditor)>dispatchOnKeyboardEvent: 0x8864a20: a(n) SmalltalkEditor 0x7fffef698078 M SmalltalkEditor(TextEditor)>keyStroke: 0x8864a20: a(n) SmalltalkEditor 0x7fffef6980b8 M [] in TextMorphForEditView(TextMorph)>keyStroke: 0x867ea40: a(n) TextMorphForEditView 0x7fffef698108 M TextMorphForEditView(TextMorph)>handleInteraction:fromEvent: 0x867ea40: a(n) TextMorphForEditView 0x7fffef698148 M TextMorphForEditView>handleInteraction:fromEvent: 0x867ea40: a(n) TextMorphForEditView 0x7fffef698198 M [] in TextMorphForEditView(TextMorph)>keyStroke: 0x867ea40: a(n) TextMorphForEditView 0x7fffef6981e8 M ECToolSet class>codeCompletionAround:textMorph:keyStroke: 0x7249388: a(n) ECToolSet class 0x7fffef698230 M ToolSet class>codeCompletionAround:textMorph:keyStroke: 0x2db08c8: a(n) ToolSet class 0x7fffef698278 M TextMorphForEditView(TextMorph)>keyStroke: 0x867ea40: a(n) TextMorphForEditView 0x7fffef6982b8 M TextMorphForEditView>keyStroke: 0x867ea40: a(n) TextMorphForEditView 0x7fffef6982f8 M TextMorphForEditView(Morph)>handleKeystroke: 0x867ea40: a(n) TextMorphForEditView 0x7fffef698338 M TextMorphForEditView(TextMorph)>handleKeystroke: 0x867ea40: a(n) TextMorphForEditView 0x7fffef698370 M KeyboardEvent>sentTo: 0x2601398: a(n) KeyboardEvent 0x7fffef6983b0 M TextMorphForEditView(Morph)>handleEvent: 0x867ea40: a(n) TextMorphForEditView 0x7fffef6983e8 M TextMorphForEditView(Morph)>handleFocusEvent: 0x867ea40: a(n) TextMorphForEditView 0x7fffef698430 M MorphicEventDispatcher>doHandlingForFocusEvent:with: 0x2600188: a(n) MorphicEventDispatcher 0x7fffef63fe38 M MorphicEventDispatcher>dispatchFocusEvent:with: 0x2600188: a(n) MorphicEventDispatcher 0x7fffef63fe78 M TextMorphForEditView(Morph)>processFocusEvent:using: 0x867ea40: a(n) TextMorphForEditView 0x7fffef63feb8 M TextMorphForEditView(Morph)>processFocusEvent: 0x867ea40: a(n) TextMorphForEditView 0x7fffef63ff08 M [] in HandMorph>sendFocusEvent:to:clear: 0x747d0b0: a(n) HandMorph 0x7fffef63ff48 M BlockClosure>ensure: 0x2600070: a(n) BlockClosure 0x7fffef63ff88 M KeyboardEvent(MorphicEvent)>becomeActiveDuring: 0x25ff8b8: a(n) KeyboardEvent 0x7fffef63ffd8 M [] in HandMorph>sendFocusEvent:to:clear: 0x747d0b0: a(n) HandMorph 0x7fffef640018 M BlockClosure>ensure: 0x25ffea0: a(n) BlockClosure 0x7fffef640058 M HandMorph>becomeActiveDuring: 0x747d0b0: a(n) HandMorph 0x7fffef6400a8 M [] in HandMorph>sendFocusEvent:to:clear: 0x747d0b0: a(n) HandMorph 0x7fffef6400e8 M BlockClosure>ensure: 0x25ffcd0: a(n) BlockClosure 0x7fffef640128 M PasteUpMorph>becomeActiveDuring: 0x747d000: a(n) PasteUpMorph 0x7fffef640170 M HandMorph>sendFocusEvent:to:clear: 0x747d0b0: a(n) HandMorph 0x7fffef6401c8 M HandMorph>sendEvent:focus:clear: 0x747d0b0: a(n) HandMorph 0x7fffef640210 M HandMorph>sendKeyboardEvent: 0x747d0b0: a(n) HandMorph 0x7fffef640250 M HandMorph>handleEvent: 0x747d0b0: a(n) HandMorph 0x7fffef6402a8 M HandMorph>processEvents 0x747d0b0: a(n) HandMorph 0x7fffef6402e0 M [] in AnimWorldState(WorldState)>doOneCycleNowFor: 0x7488298: a(n) AnimWorldState 0x7fffef640328 M Array(SequenceableCollection)>do: 0x748cdc8: a(n) Array 0x7fffef640360 M AnimWorldState(WorldState)>handsDo: 0x7488298: a(n) AnimWorldState 0x7fffef6403a0 M AnimWorldState(WorldState)>doOneCycleNowFor: 0x7488298: a(n) AnimWorldState 0x7fffef6403d8 M AnimWorldState(WorldState)>doOneCycleFor: 0x7488298: a(n) AnimWorldState 0x7fffef640410 M PasteUpMorph>doOneCycle 0x747d000: a(n) PasteUpMorph 0x7fffef640440 M [] in AnimMorphicProject>spawnNewProcess 0x747cf20: a(n) AnimMorphicProject 0x87c5278 s [] in BlockClosure>newProcess
Most recent primitives at: at: at: at: at: at: at: at: at: at: at: at: at: at: bitLengthAt: bitLengthAt: bitLengthAt: maxCode maxCode maxCode maxCode maxCode maxCode maxCode maxCode maxCode maxCode maxCode at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: basicNew isOfSameSizeCheck: isOfSameSizeCheck: at: at: value:value: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: at: bitPosition bitPosition bitPosition << basicNew size on:from:to: on:from:to: at: nextBits:put: nextBits:put: nextBits:put: byteAt:put: byteAt:put: nextBytePut: bitXor: growTo: growTo: max: max: max: max: replaceFrom:to:with:startingAt: encodeLengthField: value value value value value originalContents originalContents originalContents originalContents originalContents nextPutAll: at: at: at: at: size size size size objectAt: basicNew size at: at: at: perform: size header createMethod:class:header: newMethod:header: newMethod:header: newMethod:header: newMethod:header: at: at: at:put: at:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: objectAt:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: at:put: basicNew withArgs:executeMethod: @ basicNew depth combinationRule: basicNew basicNew width height at: squared squared copyBits
stack page bytes 8192 available headroom 5576 minimum unused headroom 6024
(Segmentation fault) ```
I was able to reproduce the crash on macOS with `201901172323`.
2^31 is most certainly a signed int overflow. it is not representable on 32 bits and will wrap to -2^31. Then, it will most probably result in buffer overflow (or underflow).
If I compile debug VM with `-fsanitize=undefined` then run the snippet, I get this:
``` ../../spur64src/vm/gcc3x-cointerp.c:52645:33: runtime error: signed integer overflow: -1752183416206057520 * 16807 cannot be represented in type 'long'
(((usqInt)destIndex)) < endOfDestination 2226
Segmentation fault Thu Nov 21 22:37:33 2019
VM: 201911090934-compile_legacy_Mac_OS nicolas@MBP-de-Nicolas:Smalltalk/OpenSmalltalk/opensmalltalk-vm Date: Sat Nov 9 10:34:10 2019 CommitHash: 30315747a Plugins: 201911090934-compile_legacy_Mac_OS nicolas@MBP-de-Nicolas:Smalltalk/OpenSmalltalk/opensmalltalk-vm
C stack backtrace & registers: rax 0xffffffff0fcd2df8 rbx 0x00000001064c9900 rcx 0xffffffff0fcd2df8 rdx 0x0000000000000001 rdi 0x00007fff9da40f01 rsi 0x0000000000000000 rbp 0x00007ffeea108440 rsp 0x00007ffeea1082f0 r8 0x00000000000130a8 r9 0x00007fff9da40f78 r10 0x0000000000000000 r11 0x00007fff9da40f70 r12 0x00007fff9642c818 r13 0x00007fff9642c838 r14 0x000000010bf6e900 r15 0x000000010b9033a0 rip 0x0000000105f39c51 0 Squeak 0x0000000105f39c51 copyLoopNoSource + 993 1 Squeak 0x0000000105e5517d reportStackState + 589 2 Squeak 0x0000000105e55d19 sigsegv + 681 3 libsystem_platform.dylib 0x00007fff673b7b5d _sigtramp + 29 4 ??? 0x0000000000000001 0x0 + 1 5 Squeak 0x0000000105f2fb71 copyBitsLockedAndClipped + 4129 6 Squeak 0x0000000105f296e6 copyBits + 134 7 Squeak 0x0000000105f29a23 primitiveCopyBits + 67 8 ??? 0x000000010b1e0670 0x0 + 4481484400 9 Squeak 0x0000000105aafa65 interpret + 517 10 Squeak 0x0000000105e59d87 -[sqSqueakMainApplication runSqueak] + 615 11 Foundation 0x00007fff3d5ae756 __NSFirePerformWithOrder + 362 12 CoreFoundation 0x00007fff3b29e6d8 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 13 CoreFoundation 0x00007fff3b29e60d __CFRunLoopDoObservers + 451 14 CoreFoundation 0x00007fff3b240d30 __CFRunLoopRun + 1136 15 CoreFoundation 0x00007fff3b24066e CFRunLoopRunSpecific + 455 16 HIToolbox 0x00007fff3a49f1ab RunCurrentEventLoopInMode + 292 17 HIToolbox 0x00007fff3a49eded ReceiveNextEventCommon + 355 18 HIToolbox 0x00007fff3a49ec76 _BlockUntilNextEventMatchingListInModeWithFilter + 64 19 AppKit 0x00007fff3883777d _DPSNextEvent + 1135 20 AppKit 0x00007fff3883646b -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1361 21 AppKit 0x00007fff38830588 -[NSApplication run] + 699 22 AppKit 0x00007fff3881fac8 NSApplicationMain + 777 23 Squeak 0x0000000105e504ce main + 782 24 libdyld.dylib 0x00007fff671cc3d5 start + 1
Smalltalk stack dump: 0x7ffeea112aa8 M GrafPort>copyBits 0x10b9033a0: a(n) GrafPort ```
The signed integer overflow reported by -fsanitize is not related, what is related is the assert warning:
``` (((usqInt)destIndex)) < endOfDestination 2226 Process 77080 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xffffffff0d50d768) frame #0: 0x000000010048bc51 Squeak`copyLoopNoSource at BitBltPlugin.c:2227:14 2224 } 2225 destMask = mask1; 2226 assert((((usqInt)destIndex)) < endOfDestination); -> 2227 destWord = long32At(destIndex); 2228 mergeWord = mergeFnwith(halftoneWord, destWord); 2229 destWord = (destMask & mergeWord) | (destWord & ((unsigned int)~destMask)); 2230 long32Atput(destIndex, destWord); Target 0: (Squeak) stopped. ```
``` (lldb) bt * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xffffffff0d50d768) * frame #0: 0x000000010048bc51 Squeak`copyLoopNoSource at BitBltPlugin.c:2227:14 frame #1: 0x0000000100481b71 Squeak`copyBitsLockedAndClipped at BitBltPlugin.c:1505:3 frame #2: 0x000000010047b6e6 Squeak`copyBits at BitBltPlugin.c:1257:2 frame #3: 0x000000010047ba23 Squeak`primitiveCopyBits at BitBltPlugin.c:5128:2 frame #4: 0x0000000108a01670 frame #5: 0x0000000100001a65 Squeak`interpret at gcc3x-cointerp.c:2772:3 frame #6: 0x00000001003abd87 Squeak`-[sqSqueakMainApplication runSqueak](self=0x0000000101867010, _cmd="runSqueak") at sqSqueakMainApplication.m:201:2
(lldb) p/x destIndex (usqInt) $8 = 0xffffffff0d50d768 (lldb) p/x endOfDestination (usqInt) $9 = 0x000000010d741768 (lldb) p/x destX (sqInt) $32 = 0x0000000080000000 (lldb) p/x dx (int) $36 = 0x80000000 (lldb) print dx (int) $34 = -2147483648 ```
`destX` is 2^31, since it is on 64bits (signed), there is no overflow at this stage.<br> The overflow is on `dx` which is an `int`.<br> It seems that `-fsanitize=undefined` does not signal case of overflow unsigned->signed, because it is not UB...
One solution is to change the type of dx and dy to sqInt. Then, with 64 bits, it might still be possible to craft a value that will overflow, this will have to be reviewed...
Closed #447.
I cannot prove that I fixed each and every possible edge case, code is way too complex for human analysis! But at least the incriminated snippet now pass and I also tried other fancy offsets like 2^63 without crash nor horrible jam on Screen form...
Thx Nicolas
Thanks Nicolas!
vm-dev@lists.squeakfoundation.org