Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot run dcm2niix on Apple's M1 Max chip #658

Closed
devDonnn opened this issue Dec 4, 2022 · 7 comments
Closed

Cannot run dcm2niix on Apple's M1 Max chip #658

devDonnn opened this issue Dec 4, 2022 · 7 comments

Comments

@devDonnn
Copy link

devDonnn commented Dec 4, 2022

I have downloaded a version of dcm2niix for Mac OS X (macos_dcm2niix.pkg) and was able to successfully run it several times. However, after 5 or 7 tries it suddenly stopped working; I get the following in the terminal: "zsh: abort ./dcm2niix". I ran in the bash as well but this time I get: "Abort trap: 6". I've also built from the source but still get the same issue. Any ideas of why it suddenly stopped working? I have a Mac Studio with M1 Max chip which may be the cause of it.

EDIT: the program stopped working after I ran "dcm2niix -f DTIvol -g y DTI". Before I did not use -g flag. Could that have triggered some unexpected behaviour?

@neurolabusc
Copy link
Collaborator

This is an artificial limitation imposed by Apple, and is not specific to dcm2niix. Apple requires all native executables on an Apple Silicon CPU (M1/M2) to be code signed. These restrictions are not applied to emulated x86 code. Therefore, the issue is that dcm2niix does natively support Apple Silicon. One thing you can do is download and install the notarized stable release of dcm2niix. If you wish to compile any native code on your M1 you will have to codesign it yourself. Another strange peculiarity of M1 executables is that they will be quarantined if you overwrite an existing executable. Therefore, while the command line will not generate any errors, the following command will bork your executable:

sudo cp ./dcm2niix /usr/local/bin/dcm2niix

and you must run

sudo rm /usr/local/bin/dcm2niix
sudo cp ./dcm2niix /usr/local/bin/dcm2niix

It is unfortunate that Apple has done such a poor job of documenting notarization, code signing and other security features. Tools will fail without any clear explanation to the user for the error. The arcane steps evolve over time. If you do wish to notarize macOS executables, I document the method used by dcm2niix. In general, Apple is very hostile to any development that does not use XCode, so while it is possible to create your own executables, it remains a dark art.

While I appreciate Apple's attempts to protect users from Malware, the developer facing support for concepts like path randomization, sandboxing and notarization leave a lot to be desired.

@devDonnn
Copy link
Author

devDonnn commented Dec 5, 2022

Thanks a lot for the info! I had a look at the crash report and I get:

"EXC_CRASH","signal":"SIGABRT",
  "asi" : {"libsystem_c.dylib":["stack buffer overflow"]},

Is is still related to the codesigning? Based on https://developer.apple.com/forums/thread/698167 I should see
Exception Type: EXC_BAD_ACCESS (SIGKILL (Code Signature Invalid)) exception.

@neurolabusc
Copy link
Collaborator

Is this an issue with an insanely long filename that is not supported by libc? Does the same problem persist if you convert the validation images? Since the error is with a base library, I do not think this is a core dcm2niix problem. However, you can always build dcm2niix in sanitize mode to debug any exceptions:

git clone https://github.com/rordenlab/dcm2niix
cd dcm2niix/console
g++ -O1 -g -fsanitize=address -fno-omit-frame-pointer  -I.  main_console.cpp nii_foreign.cpp nii_dicom.cpp jpg_0XC3.cpp ujpeg.cpp nifti1_io_core.cpp nii_ortho.cpp nii_dicom_batch.cpp  -o dcm2niix -DmyDisableOpenJPEG
./dcm2niix /path/to/DICOMS

@devDonnn
Copy link
Author

devDonnn commented Dec 5, 2022

In case you know something about it or interested in it, here is the output that I got from running dcm2niix in the sanitize mode:

`==16886==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x00016fc5a454 at pc 0x0001007609f4 bp 0x00016fc5a3c0 sp 0x00016fc59b48
WRITE of size 21 at 0x00016fc5a454 thread T0
#0 0x1007609f0 in scanf_common(void*, int, bool, char const*, char*)+0x624 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1c9f0)
#1 0x100760e68 in wrap_fscanf+0x9c (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1ce68)
#2 0x10024395c in readIniFile nii_dicom_batch.cpp:8812
#3 0x1001a366c in main main_console.cpp:259
#4 0x1949fbe4c ()

Address 0x00016fc5a454 is located in stack of thread T0 at offset 52 in frame
#0 0x100243780 in readIniFile nii_dicom_batch.cpp:8803

This frame has 2 object(s):
[32, 52) 'Setting' (line 8809) <== Memory access at offset 52 overflows this variable
[96, 351) 'Value' (line 8809)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions are supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x1c9f0) in scanf_common(void*, int, bool, char const*, char*)+0x624
Shadow bytes around the buggy address:
0x00702dfab430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x00702dfab440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x00702dfab450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x00702dfab460: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x00702dfab470: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x00702dfab480: 00 00 00 00 f1 f1 f1 f1 00 00[04]f2 f2 f2 f2 f2
0x00702dfab490: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x00702dfab4a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07
0x00702dfab4b0: f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
0x00702dfab4c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x00702dfab4d0: 00 00 00 00 f1 f1 f1 f1 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==16886==ABORTING
zsh: abort /Users/donatas/playground/tmp/dcm2niix/console/dcm2niix`

I will try to get help from the Apple's support. Thanks for your efforts and time!

@neurolabusc
Copy link
Collaborator

I see, Apple is restricting the software from reading the ini file from the user's home directory as it is not in the applications sandbox. I presume that this is yet another security feature added by Apple. Why don't you see if this is fixed in the development version:

git clone --branch development https://github.com/rordenlab/dcm2niix
cd dcm2niix/console
make
./dcm2niix /path/to/DICOMS

@devDonnn
Copy link
Author

devDonnn commented Dec 5, 2022

Fantastic! Works well now. Thanks a lot! Can I use this development version by simply building it from the source?

@neurolabusc
Copy link
Collaborator

Yes. the make command will create a minimal build. It lacks support for the rare JPEG2000 and JPEG-LS transfer syntaxes. If you want the full fat version of dcm2niix you can use cmake:

git clone  --branch development  https://github.com/rordenlab/dcm2niix.git
cd dcm2niix
mkdir build && cd build
cmake -DZLIB_IMPLEMENTATION=Cloudflare -DUSE_JPEGLS=ON -DUSE_OPENJPEG=ON ..
make

I do think we are getting ready for a new stable release. @ningfei if you have a chance, it would be great to have your expert thoughts on issues 629 and 647. Those cmake questions are outside my expertise, but seem the last remaining unresolved issues.

@devDonnn devDonnn closed this as completed Dec 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants