nocmodl translator segfaults with STATE array variables and KINETIC block
Context
When translating MOD file containing array STATE variable and KINETIC block I see segfault.
Overview of the issue
If we take cal4.mod from ModelDB and try to translate it then we see:
✗ ./bin/nocmodl /Users/kumbhar/workarena/repos/bbp/nrn-hack-mod-cpp/last_review/last_review/last_review_1/150551/AshhadNarayanan2013/cal4.mod
Translating /Users/kumbhar/workarena/repos/bbp/nrn-hack-mod-cpp/last_review/last_review/last_review_1/150551/AshhadNarayanan2013/cal4.mod into /Users/kumbhar/workarena/repos/bbp/nrn-hack-mod-cpp/last_review/last_review/last_review_1/150551/AshhadNarayanan2013/cal4.c
[2] 45092 segmentation fault ./bin/nocmodl
Expected result/behavior
MOD file should be translated to .c file successfully.
NEURON setup
- Version: master, 8.1 or 8.0.1
- Installation method : cmake or pip
- OS + Version: MacOS (at least)
- Compiler + Version: AppleClang
Minimal working example - MWE
-
Build neuron "as usual"
-
Download above mentioned mod file
-
Try to convert it using nocmodl
-
CMake build commands:
cmake -DNRN_ENABLE_RX3D=OFF -DNRN_ENABLE_INTERVIEWS=OFF -DNRN_ENABLE_CORENEURON=OFF .. -DCMAKE_INSTALL_PREFIX=`pwd`/install
Logs
➜ build git:(7774c0d04) ✗ lldb bin/nocmodl /Users/kumbhar/workarena/repos/bbp/nrn-hack-mod-cpp/last_review/last_review/last_review_1/150551/AshhadNarayanan2013/cal4.mod
(lldb) target create "bin/nocmodl"
Current executable set to '/Users/kumbhar/workarena/repos/bbp/nrn/build/bin/nocmodl' (x86_64).
(lldb) settings set -- target.run-args "/Users/kumbhar/workarena/repos/bbp/nrn-hack-mod-cpp/last_review/last_review/last_review_1/150551/AshhadNarayanan2013/cal4.mod"
(lldb) r
Process 45169 launched: '/Users/kumbhar/workarena/repos/bbp/nrn/build/bin/nocmodl' (x86_64)
Translating /Users/kumbhar/workarena/repos/bbp/nrn-hack-mod-cpp/last_review/last_review/last_review_1/150551/AshhadNarayanan2013/cal4.mod into /Users/kumbhar/workarena/repos/bbp/nrn-hack-mod-cpp/last_review/last_review/last_review_1/150551/AshhadNarayanan2013/cal4.c
Process 45169 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x000000010001e779 nocmodl`slist_data(s=0x0000600000c08330, indx=20, findx=1) at nocpout.c:2261:7
2258 if (s->slist_info_) {
2259 /* i'd use realloc but to avoid portability problems */
2260 /* this probably will never get executed anyway */
-> 2261 n = s->slist_info_[0] + 1;
2262 pi = (int*)emalloc((1 + 2*n)*sizeof(int));
2263 for (i=2*(n-1); i > 0; --i) {
2264 pi[i] = s->slist_info_[i];
Target 0: (nocmodl) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
* frame #0: 0x000000010001e779 nocmodl`slist_data(s=0x0000600000c08330, indx=20, findx=1) at nocpout.c:2261:7
frame #1: 0x0000000100016982 nocmodl`kinlist(fun=0x0000600002108d20, rlst=0x00006000021047d0) at kinetic.c:1170:3
frame #2: 0x0000000100013a25 nocmodl`kinetic_intmethod(fun=0x0000600002108d20, meth="NEURON's CVode") at kinetic.c:547:2
frame #3: 0x0000000100015564 nocmodl`cvode_kinetic(qsol=0x000060000020e020, fun=0x0000600002108d20, numeqn=24, listnum=1) at kinetic.c:1520:2
frame #4: 0x000000010002ca62 nocmodl`solvhandler at solve.c:236:5
frame #5: 0x00000001000175c5 nocmodl`main(argc=2, argv=0x00007ff7bfeff760) at modl.c:177:2
frame #6: 0x000000010006551e dyld`start + 462
(lldb) print s
(Symbol *) $0 = 0x0000600000c08330
(lldb) print s->slist_info_
(int *) $1 = 0x695f2029746e6928
(lldb) print s->slist_info_[0]
error: Couldn't apply expression side effects : Couldn't dematerialize a result variable: couldn't read its memory
- This was encountered while testing https://github.com/ModelDBRepository/150551/pull/1
- Note that the issue is reproducible with older versions of the neuron than the master (8.0.1 or 8.1) with the original mod file from ModelDB. So the C++ changes are not relevant here.
Interesting. I'm not seeing the problem with Ubuntu 22.4 (gcc 11.2.0) and current master
$ nrniv
NEURON -- VERSION 8.2.dev-53-g4873aed70 master (4873aed70) 2022-05-24
Additional mechanisms from files "cal4.mod"
I'll try on my mac.
👍 -- I also saw that it didn't crash in the Ubuntu/GCC-based CI, only locally on macOS.
Looks like valgrind has something to say about it.
Translating cal4.mod into cal4.c
==315754== Invalid write of size 8
==315754== at 0x113746: massagekinetic(Item*, Item*, Item*, Item*, int) (kinetic.cpp:479)
==315754== by 0x13795A: yyparse() (parse1.ypp:1058)
==315754== by 0x117801: main (modl.cpp:163)
==315754== Address 0x54eb7f8 is 8 bytes before a block of size 48 alloc'd
==315754== at 0x4E04FB5: malloc (vg_replace_malloc.c:380)
==315754== by 0x1171D1: emalloc(unsigned int) (list.cpp:220)
==315754== by 0x1135EB: massagekinetic(Item*, Item*, Item*, Item*, int) (kinetic.cpp:464)
==315754== by 0x13795A: yyparse() (parse1.ypp:1058)
==315754== by 0x117801: main (modl.cpp:163)
==315754==
The tentative diagnosis is that bufm and cabufm are listed in the COMPARTMENT statement but the kinetic equation in which they appear is commented out
:~ ca[i] + bufm[i] <-> cabufm[i] (kfm*dsqvol, (0.001)*KDm*kfm...
Because there was no use of those states, their Symbol->usage value was 0 and so line 479
rlist->capacity[SYM(q1)->used - 1] = ...
got written into it's -1 element which caused the segfault on the mac later on. (This last line is speculative). The solution is to comment out (or remove) every line or use of those two STATE variables. I should also, perhaps, decide if recovery is possible or if an error message should be generated. Anyway, valgrind is clean if those two STATEs are removed.