kevinlawler / kona

Open-source implementation of the K programming language
ISC License
1.36k stars 138 forks source link

Consistent crash possibly from missing space around drop. #608

Closed gitonthescene closed 2 years ago

gitonthescene commented 2 years ago

This is probably illegal, but it crashes kona consistently:

split:{(0,x-!#x)_y[~x]}
tavmem commented 2 years ago

Well ... yes ... it is illegal ... and the illegality is indeed due to missing space around drop.

On page 63 of the K2.0 Reference Manual (which you can get to from the wiki), the syntax for "Drop/Cut" is defined as x _ y

Nevertheless, kona should not crash.

K3.2 reports a "parse error" (and does not crash).

gitonthescene commented 2 years ago

That's what I figured and so I thought it worth posting. I probably should have said I ran this on a Mac and build with make k-libc. I can provide more info if you think it would be helpful.

tavmem commented 2 years ago

Not necessary ... I am able to replicate the problem. But, thank you for offering the info.

bakul commented 2 years ago

@gitonthescene, are you by any chance talking about ngn/k? Its Makefile has a k-libc target, Kona's doesn't.

gitonthescene commented 2 years ago

@bakul You're absolutely right. I looked through my history to try to remember how I built this and didn't remember that that make command was used to build ngn/k. In any event, the crash definitely came from running kona. Sorry for the confusion.

tavmem commented 2 years ago

However, this works with no spaces around drop:

tavme@DESKTOP-FVKENU9 MINGW64 ~/kona
$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  1_1 2 3
2 3

and this results in the appropriate error msg::

  a:1
  b:1 2 3
  a_b
value error
a_b
^

and so does this:

  a _b
value error
_b
^
tavmem commented 2 years ago

This is OK, with no spaces:

[tom@localhost kona]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {x_y}
{x_y}

This crashes, with no spaces:

[tom@localhost kona]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {(x)_y}
Segmentation fault (core dumped)

It's OK with no leading space:

[tom@localhost kona]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {(x)_ y}
{(x)_ y}

It crashes with no trailing space:

[tom@localhost kona]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {(x) _y}
Segmentation fault (core dumped)
tavmem commented 2 years ago

How k2.8 handles some of these cases:

[tom@localhost k2.8]$ rlwrap -n ./k
K 2.8 2000-10-10 Copyright (C) 1993-2000 Kx Systems
\ for help. \\ to exit.

  x _ y
value error
y
^
parse error

  x _y
reserved error
x _y
  ^
parse error

  {x_y}
{x_y}

  {x_ y}
{x_ y}

  {x _y}
reserved error
x _y
  ^
parse error

  {(x) _ y}
{(x) _ y}

  {(x)_y}
reserved error
(x)_y
   ^
parse error

  {(x)_ y}
{(x)_ y}

  {(x) _y}
reserved error
(x) _y
    ^
parse error

... and hence, how kona should handle them.

gitonthescene commented 2 years ago

FWIW, that feels right to me. The only cause for confusion is when it is attached to an identifier.

tavmem commented 2 years ago

Agreed ...

Alhough the primary problem (and reason for this issue) is the crashes, there are other (far less critical) differences between kona and k2.8

tom@localhost kona]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  x _y
value error
x
^

and, also In k2.8

K 2.8 2000-10-10 Copyright (C) 1993-2000 Kx Systems
\ for help. \\ to exit.

  _x
reserved error
_x
^
parse error

  _x:2
reserved error
_x:2
^
parse error

In kona:

[tom@localhost kona]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  _x
value error
_x
^

  _x:2
reserved error
>
tavmem commented 2 years ago

The simplest crash case in kona appears to be the following:

[tom@localhost k2.8]$ rlwrap -n ./k
K 2.8 2000-10-10 Copyright (C) 1993-2000 Kx Systems 
\ for help. \\ to exit.

  {_y}
reserved error
_y
^
parse error
[tom@localhost kona]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {_y}
Segmentation fault (core dumped)

Resolving that crash may also fix the others.

In particular, note that there is no crach when there is no function:

[tom@localhost kona]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  _y
value error
_y
^
tavmem commented 2 years ago

The next step is to determine WHERE and WHY the crash occurs. Note that there was a "core dump" and that could be examined. For kona, I prefer using the version of kona that is in tavmem/ks

Note the tavmem/ks doesn't load ggg if there is a crash. So I copied the screen output to ggg, and then ran the step that creates ksd and kss

The last lines of ksd are:

            n2      u: _y     in if(func)
             func *********************************************************************************
                 0x7fceb63057c0 0x7fceb63057d8            1-6 -3 2   "_y"
            s ------------------------------------------------------------------------------------
            s: _y
            u: _y
              ~FX *denameS(.k,u,0)      K* denameS(S dir_string, S t, I create) <- I capture(S s, I n, I k, I *m, V *w, I *d, K *locals, K *dict,K func)       BEG denameS
                  dir_string: .k      t: _y      create: 0
                ~CJ denameD(&KTREE,dir_string,create)      K* denameD(K*d, S t, I create) <- K* denameS(S dir_string, S t, I create)      BEG denameD
                    d: 0x458da8      t: .k      create: 0      &KTREE: 0x458da8
                  ~CK denameRecurse('.'==*t||!*t?&KTREE:d,t,create)      K* denameRecurse(K *p,S t,I create) <- K* denameD(K *d,S t,I create)      BEG denameRecurse
                        p: 0x458da8      t: .k      create: 0      sd_(*p,0):     0x7fceb6305200 0x7fceb6305218            1-6 5 2   
                  BEG sp   k
                    ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
                    #FN sp :: SC(k,p->k)  a: -1
                    ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
                    #FO sp :: LINK(p,a)  q: 0x7fceb6305240
                    ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
                    #FN sp :: SC(k,p->k)  a: 0
                  BEG DE
                      sd_(d,0):     0x7fceb6305200 0x7fceb6305218            1-6 5 2   
                      b: k
                    ~ER DI(d,i)      K DI(K d, I i) <- K DE(K d,S b)      BEG DI
                        sd_(d,0):     0x7fceb6305200 0x7fceb6305218            1-6 5 2   
                        i: 0
                    #ER DE :: K x=DI(d,i)
                     ER:  sd(x):     0x7fceb6305280 0x7fceb6305298            1-6 0 3   
                  (`k;;)
                    ~ES ES(d)      S ES(K d) <- K DE(K d,S b)      BEG ES
                    #ES ES :: s=ES(x)
                     ES:  k
                  test if(b==s)  b:k  s:k
                    ~CL EVP(e)      K* EVP(K e) <- K* denameRecurse(K *p,S t,I create)      BEG EVP
                        &e: 0x7ffc07245d28      sd_(e,0):      0x7fceb6305280 0x7fceb6305298            1-6 0 3   
                    #CL denameRecurse :: EVP(e)  p: 0x7fceb63052a0      sd_(*p,1):     0x7fceb6305040 0x7fceb6305058            6-6 6 0   
                    ~CM denameRecurse(p,t,create)      K* denameRecurse(K*p,S t,I create) <- K* denameRecurse(K*p,S t,I create)      BEG denameRecurse
                          p: 0x7fceb63052a0      t:       create: 0      sd_(*p,0):     0x7fceb6305040 0x7fceb6305058            6-6 6 0   
                    #CM denameRecurse :: denameRecurse(p,t,create)  z: 0x7fceb63052a0      sd_(*z,0):      0x7fceb6305040 0x7fceb6305058            6-6 6 0   
                  #CK denameD :: denameRecurse('.'==*t||!*t?&KTREE:d,t,create)  v: 0x7fceb63052a0   sd_(*v,0):     0x7fceb6305040 0x7fceb6305058            6-6 6 0   
                #CJ denameS :: denameD(&KTREE,dir_string,create)
                ~CO denameD('.'==*t||!*t?&KTREE:denameD(&KTREE,dir_string,create),t,create)      K* denameD(K*d, S t, I create) <- K* denameS(S dir_string, S t, I create)     BEG denameD
                    d: 0x7fceb63052a0      t: _y      create: 0      &KTREE: 0x458da8
                  ~CK denameRecurse('.'==*t||!*t?&KTREE:d,t,create)      K* denameRecurse(K *p,S t,I create) <- K* denameD(K *d,S t,I create)      BEG denameRecurse
                        p: 0x7fceb63052a0      t: _y      create: 0      sd_(*p,0):     0x7fceb6305040 0x7fceb6305058            6-6 6 0   
                  BEG sp   _y
                    ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
                    #FN sp :: SC(k,p->k)  a: -1
                    ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
                    #FO sp :: LINK(p,a)  q: 0x7fceb6305240
                    ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
                    #FN sp :: SC(k,p->k)  a: -1
                    ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
                    #FO sp :: LINK(p,a)  q: 0x7fceb63050c0
                    ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
                    #FN sp :: SC(k,p->k)  a: 1
                    ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
                    #FO sp :: LINK(p,a)  q: 0x7fceb6305980
                    ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
                    #FN sp :: SC(k,p->k)  a: 0
                  #CK denameD :: denameRecurse('.'==*t||!*t?&KTREE:d,t,create)  v: (nil)   sd_(*v,0):  NOT v
                #CO denameS :: denameD('.'==*t||!*t?&KTREE:denameD(&KTREE,dir_string,create),t,create)  v: (nil)   sd_(*v,0):  NOT v
              Segmentation fault (core dumped)

It shows that the crash occured at #CO This is where the function denamsS returns a nil result. Scrolling up, and based on the indentation, we see that denameS was called at ~FX by the function capture. We also see that catpure was going to assume the result of denamS was a pointer, and use the contents. Of course, a nil result as a pointer has no contents, and hence the crash.

We can use grep to find where this occurs:

[tom@localhost ks]$ grep "#CO" src/*.c
src/v.c:  O("#CO denameS :: denameD('.'==*t||!*t?&KTREE:denameD(&KTREE,dir_string,create),t,create)  v: %p   sd_(*v,0):",v); if(v)sd_(*v,0); else O("  NOT v\n");

and

[tom@localhost ks]$ grep "~FX" src/*.c
src/p.c:                        O("~FX *denameS("".k"",u,0)      K* denameS(S dir_string, S t, I create) <- I capture(S s, I n, I k, I *m, V *w, I *d, K *locals, K *dict,K func)");

So ... in tavmem/ks, the call & return is in src/p.c at:

                        O("~FX *denameS("".k"",u,0)      K* denameS(S dir_string, S t, I create) <- I capture(S s, I n, I k, I *m, V *w, I *d, K *locals, K *dict,K func)");
                        h=*denameS(".k",u,0);
                        O("#FX capture :: *denameS("".k"",u,0)\n");

in kevinlawler/kona it's in src/p.c at:

    CS(MARK_NAME,     e=strdupn(s+k,r);
                      u=sp(e); //converting to sp() probably unnecessary
                      free(e);
                      P(!u,(L)ME) //you can return 0 but catch above?
                      K q;
                      //      it uses the non-path-creating form of dename
                      if(2==r && '_'==*u && stringHasChar(n_s,u[1]))
                        if('f'==u[1]){ z=func?ci(func):_n(); }   //TODO: stack error --- but be careful to generalize.
                          // proper soln will handle cycle f:{ g 0} g:{f 0}
                          // see "getrusage" or http://stackoverflow.com/questions/53827/checking-available-stack-size-in-c
                        else z=((K(*)())vn_[charpos(n_s,u[1])])();
                      else if(func)
                      { h=*denameS(".k",u,0);
gitonthescene commented 2 years ago

I have a ways to go before I can follow this, but I appreciate your explaining the process. I’ll try to reproduce with ks and then try understanding.

tavmem commented 2 years ago

Exploring why there is no crash with no function:( i.e. with just _y ): Using tavmem/ks ksd shows:

        ~BY capture(s2,y,i,m,w,&c,(K*)kV(v)+LOCALS, dict,func)      I capture(S s, I n, I k, I *m, V *w, I *d, K *locals, K *dict, K func) <- K wd_(S s, int n, K *dict, K func)      BEG capture
            s: _y
            n: 2    k: 0    *m: -8    *w: (nil)    *d: 0
            *locals:     0x7fb1d1f87680 0x7fb1d1f87698            1-6 5 0   
        .()
            dict: 0x7fb1d1f872a0      sd_(*dict,0):     0x7fb1d1f87040 0x7fb1d1f87058            6-6 6 0   
            func:
        name   BEG sp   _y
          ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
          #FN sp :: SC(k,p->k)  a: -1
          ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
          #FO sp :: LINK(p,a)  q: 0x7fb1d1f870c0
          ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
          #FN sp :: SC(k,p->k)  a: 1
          ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
          #FO sp :: LINK(p,a)  q: 0x7fb1d1f87480
          ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
          #FN sp :: SC(k,p->k)  a: -1
          ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
          #FO sp :: LINK(p,a)  q: 0x7fb1d1f87240
          ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
          #FN sp :: SC(k,p->k)  a: -1
          ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
          #FO sp :: LINK(p,a)  q: (nil)
          ~FP newN()      N newN() <- S sp(S k)      BEG newN
            ~FQ unpool(lsz(sizeof(Node)))      V unpool(I r) <- N newN()      /nBEG unpool   r: 6
                *L: 0x7fb1d1f87740   mUsed: 1984.000000   k: 64   *z=0;   r: 6   *z: 0x7fb1d1f87780   done
            #FQ newN :: unpool(lsz(sizeof(Node)))
          #FP sp :: newN()
          ~FR SC(k,s->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
          #FR sp :: SC(k,s->k)
          ~FS SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
          #FS sp :: SC(k,p->k)
          ~FS SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
          #FS sp :: SC(k,p->k)
        KK2
        n3      u: _y
          ~BZ inKtree( dict,u,0)      K *inKtree(K *d, S t, I create) <- I capture(S s, I n, I k, I *m, V *w, I *d, K *locals, K *dict, K func)     BEG inKtree 
              t: _y      create:0    d: 0x7fb1d1f872a0      sd_(*d,0):     0x7fb1d1f87040 0x7fb1d1f87058            6-6 6 0   
            ~DG inKtreeR('.'==*t||!*t?&KTREE:d,t,create)      K* inKtreeR(K*p,S t,I create) <- K* inKtree(K*d, S t, I create)      BEG inKtreeR
                t: _y      create:0      sd_('.'==*t||!*t?&KTREE:d,0):     0x7fb1d1f87040 0x7fb1d1f87058            6-6 6 0   
            BEG sp   _y
              ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
              #FN sp :: SC(k,p->k)  a: -1
              ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
              #FO sp :: LINK(p,a)  q: 0x7fb1d1f87240
              ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
              #FN sp :: SC(k,p->k)  a: -1
              ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
              #FO sp :: LINK(p,a)  q: 0x7fb1d1f870c0
              ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
              #FN sp :: SC(k,p->k)  a: 1
              ~FO LINK(p,a)      LINK(n,x) <- S sp(S k)      
              #FO sp :: LINK(p,a)  q: 0x7fb1d1f87740
              ~FN SC(k,p->k)      I SC(S a,S b) <- S sp(S k)      BEG SC
              #FN sp :: SC(k,p->k)  a: 0
            ******************* kerr on leaading underbar
            #DG inKtree :: inKtreeR('.'==*t||!*t?&KTREE:d,t,create)
             DG: z: (nil)      sd(*(K*)z):
          #BZ capture :: inKtree( dict,u,0)
           BZ: z: (nil)      sd(*(K*)z):
              fbr: 0   fdc: 0
        value error
        _y
        ^
        #BY wd_ :: capture(s2,y,i,m,w,&c,(K*)kV(v)+LOCALS,dict,func)
         BY: j: 0
            cd -- !x
            cd                 0x7fb1d1f86000 0x7fb1d1f86018            1-7 7 0   
            cd -- !x
            cd                 0x7fb1d1f87680 0x7fb1d1f87698            1-6 5 0   
      .()
            cd                 0x7fb1d1f87640 0x7fb1d1f87658            1-6 5 0   
      .()
            cd -- !x
            cd -- !x
            cd -- !x
            cd                 0x7fb1d1f87600 0x7fb1d1f87618            1-6 -1 3   -8 8 0
            cd                 0x7fb1d1f876c0 0x7fb1d1f876d8            1-6 -3 2   "_y"
            cd                 0x7fb1d1f87700 0x7fb1d1f87718            1-6 -4 2   (nil)  (nil)  
      #BS wd :: wd_(s,n, denameD(&KTREE,d_,1),0)      sd(res):
     0x7ffcad3c8598     
    #BQ line :: wd(*a,*n)
     BQ: sd(zz):     

    ~BR ex(zz)      K ex(K a) <- I line(FILE*f, S*a, I*n, PDA*p)      BEG ex 
    sd_(a,2):     

    exA 1 *****************************************************************************

    #BR line :: ex(zz)

  result: 0x7ffcad3c85f8

'wd_' calls 'capture' at ~BY 'capture' calls 'inKtree' at ~BZ 'inKtree' calls 'inKtreeR' at ~DG 'inKtreeR' executes a 'kerr' on leading underbar 'value error' is reported ... and no crash

tavmem commented 2 years ago

-y works in kona The section of inKtreeR that catches the value errer using kerr is:

Z K* inKtreeR(K *p,S t,I create)
{ //O("BEG inKtreeR\n"); O("    t: %s      create:%lld",t,create);  O("    p: %p      sd_(*p,0):",p);sd_(*p,0);
  if(!*t) R p;
  if('.'==*t) t++;
  I c=0,a=(*p)->t;
  while(t[c] && '.'!=t[c]) c++;
  S u=strdupn(t,c);   //oom
  S k=sp(u);   //oom
  free(u); t+=c;
  P('_'==*k,(K*)kerr("reserved"))// ... not positive this goes here. does it fit in LOC? or parser maybe?

{-y} crashes in kona. The problem begins in denameRecurse But, we expect that the error should have been caught there. There is a similar code structure designed to catch a leading underscore:

Z K*inKtreeR(K*p,S t,I create)
{ if(!*t) R p;
  if('.'==*t) t++;
  I c=0,a=(*p)->t;
  while(t[c] && '.'!=t[c]) c++;
  S u=strdupn(t,c);//oom
  S k=sp(u); //oom
  free(u);
  t+=c;
  P('_'==*k,(K*)kerr("reserved"))   // ... not positive this goes here. does it fit in LOC? or parser maybe?

For some reason kerr was not executed in denameRecurse for {_y}

gitonthescene commented 2 years ago

I’m still not up to reading the code but it occurred to me that the initial _ is acceptable for names of system functions such as _bin. I wonder handling this case factors in to how this error is detected.

tavmem commented 2 years ago

Not clear what is happening ...

If I add the following 3 lines to src/v.c in kona:

diff --git a/src/v.c b/src/v.c
index c47fd19..759865b 100644
--- a/src/v.c
+++ b/src/v.c
@@ -62,6 +62,7 @@ K lookupEntryOrCreate(K *p, S k) {    //****only *dict or *_n are passed to here
 }

 Z K* denameRecurse(K*p,S t,I create) {
+  O("\n\nBEG denameRecurse      p: %p      t: %s      create: %lld      ",p,t,create); O("show(*p):");show(*p);
   if(!*t)R p;
   if('.'==*t)t++;
   I c=0,a=(*p)->t;
@@ -70,10 +71,11 @@ Z K* denameRecurse(K*p,S t,I create) {
   S k=sp(u); //oom
   free(u);
   t+=c;
+  O("before test to execute kerr\n");
   P('_'==*k,(K*)kerr("reserved"))// ... not positive this goes here. does it fit in LOC? or parser maybe?
-
   //Probably the below error check (and any others in front of LOC) should be moved into LOC
   //and LOC should have the potential to return 0 (indicating other errors as well, e.g. out of memory)
+  O("after test to execute kerr\n");
   P(!(6==a || 5==a),(K*)TE)
   K e=0;
   if(create) { e=lookupEntryOrCreate(p,k); P(!e,(K*)ME) }
[tom@localhost kona]$

then:

[tom@localhost kona]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {_y}

BEG denameRecurse      p: 0x44edc8      t: .k      create: 1      show(*p):.((`k;;)
  (`t;-4.104833e+08;))
before test to execute kerr
after test to execute kerr

BEG denameRecurse      p: 0x7f21b08272a0      t:       create: 1      show(*p):

BEG denameRecurse      p: 0x7fff2c65e948      t: _y      create: 1      show(*p):.()
before test to execute kerr

BEG denameRecurse      p: 0x44edc8      t: .k      create: 0      show(*p):.((`k;;)
  (`t;-4.104833e+08;))
before test to execute kerr
after test to execute kerr

BEG denameRecurse      p: 0x7f21b08272a0      t:       create: 0      show(*p):

BEG denameRecurse      p: 0x7f21b08272a0      t: _y      create: 0      show(*p):before test to execute kerr
Segmentation fault (core dumped)
[tom@localhost kona]$ 

We get some surprising results:

tavmem commented 2 years ago

It turns out that this is a problem created when "fixing" issue #537 - early binding

Using the second of the 2 commits done on Sep 14, 2019 we get:

tom@localhost k190914b]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {_y}
{_y}
reserved error
> 

Using the only commit done on Oct 3. 2019 we get:

[tom@localhost k191003]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {_y}
Segmentation fault (core dumped)

The problem was caused by changes made int the commit of Oct 3, 2019

tavmem commented 2 years ago

More surprising results: I added the same 3 lines to the second commit done on Sep 14, 2019

[tom@localhost k190914b]$ git diff
diff --git a/src/v.c b/src/v.c
index 951be6a..f62f031 100644
--- a/src/v.c
+++ b/src/v.c
@@ -62,6 +62,7 @@ K lookupEntryOrCreate(K *p, S k) {    //****only *dict or *_n are passed to here
 }

 Z K* denameRecurse(K*p,S t,I create) {
+  O("\n\nBEG denameRecurse      p: %p      t: %s      create: %lld      ",p,t,create); O("show(*p):");show(*p);
   if(!*t)R p;
   if('.'==*t)t++;
   I c=0,a=(*p)->t;
@@ -70,8 +71,9 @@ Z K* denameRecurse(K*p,S t,I create) {
   S k=sp(u); //oom
   free(u);
   t+=c;
+  O("before\n");
   P('_'==*k,(K*)kerr("reserved"))// ... not positive this goes here. does it fit in LOC? or parser maybe?
-
+  O("after\n");
   //Probably the below error check (and any others in front of LOC) should be moved into LOC
   //and LOC should have the potential to return 0 (indicating other errors as well, e.g. out of memory)
   P(!(6==a || 5==a),(K*)TE)

Just to see how many times denameRecurse was called.

[tom@localhost k190914b]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {_y}

BEG denameRecurse      p: 0x44dda8      t: .k      create: 1      show(*p):.((`k;;)
  (`t;-4.10394e+08;))
before
after

BEG denameRecurse      p: 0x7f698fd2e2a0      t:       create: 1      show(*p):

BEG denameRecurse      p: 0x7ffdace96fe8      t: _y      create: 1      show(*p):.()
before

BEG denameRecurse      p: 0x44dda8      t: .k      create: 0      show(*p):.((`k;;)
  (`t;-4.10394e+08;))
before
after

BEG denameRecurse      p: 0x7f698fd2e2a0      t:       create: 0      show(*p):

BEG denameRecurse      p: 0x7f698fd2e2a0      t: _y      create: 0      show(*p):before
{_y}
reserved error
>  

Almost identical to the current state with the segfault:

Why is the reserved error message displayed only after the 2nd execution of (K*)kerr("reserved")?

tavmem commented 2 years ago

Changed show to sd_ in current kona to get more detail on the contents of *p```` on each of the 6 executions ofdenameR``` before the segfault

[tom@localhost kona]$ git diff
diff --git a/src/v.c b/src/v.c
index c47fd19..88968ba 100644
--- a/src/v.c
+++ b/src/v.c
@@ -62,6 +62,7 @@ K lookupEntryOrCreate(K *p, S k) {    //****only *dict or *_n are passed to here
 }

 Z K* denameRecurse(K*p,S t,I create) {
+  O("\n\nBEG denameRecurse      p: %p      t: %s      create: %lld      ",p,t,create); O("show(*p):");sd_(*p,2);
   if(!*t)R p;
   if('.'==*t)t++;
   I c=0,a=(*p)->t;
@@ -70,8 +71,9 @@ Z K* denameRecurse(K*p,S t,I create) {
   S k=sp(u); //oom
   free(u);
   t+=c;
+  O("before\n");
   P('_'==*k,(K*)kerr("reserved"))// ... not positive this goes here. does it fit in LOC? or parser maybe?
-
+  O("after\n");
   //Probably the below error check (and any others in front of LOC) should be moved into LOC
   //and LOC should have the potential to return 0 (indicating other errors as well, e.g. out of memory)
   P(!(6==a || 5==a),(K*)TE)

The result is:

[tom@localhost kona]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {_y}

BEG denameRecurse      p: 0x44edc8      t: .k      create: 1      show(*p):     0x7f0d6668d200 0x7f0d6668d218            1-6 5 2   
.((`k;;)
  (`t;-4.103904e+08;))
 0x7f0d6668d220     0x7f0d6668d280 0x7f0d6668d298            1-6 0 3   
(`k;;)
 0x7f0d6668d2a8     0x7f0d6668d2c0 0x7f0d6668d2d8 0x9d9350  1-6 4 1   `k
 0x7f0d6668d2a0     0x7f0d6668d040 0x7f0d6668d058            6-6 6 0   
 0x7f0d6668d298     0x7f0d6668d040 0x7f0d6668d058            6-6 6 0   
 0x7f0d6668d218     0x7f0d6668d380 0x7f0d6668d398            1-6 0 3   
(`t;-4.103904e+08;)
 0x7f0d6668d3a8     0x7f0d6668d3c0 0x7f0d6668d3d8 0x9d9370  1-6 4 1   `t
 0x7f0d6668d3a0     0x7f0d6668d300 0x7f0d6668d318            1-6 2 1   -4.103904e+08
 0x7f0d6668d398     0x7f0d6668d040 0x7f0d6668d058            6-6 6 0   
before
after

BEG denameRecurse      p: 0x7f0d6668d2a0      t:       create: 1      show(*p):     0x7f0d6668d040 0x7f0d6668d058            6-6 6 0   

BEG denameRecurse      p: 0x7ffec7ef5828      t: _y      create: 1      show(*p):     0x7f0d6668d800 0x7f0d6668d818            1-6 5 0   
.()
before

BEG denameRecurse      p: 0x44edc8      t: .k      create: 0      show(*p):     0x7f0d6668d200 0x7f0d6668d218            1-6 5 2   
.((`k;;)
  (`t;-4.103904e+08;))
 0x7f0d6668d220     0x7f0d6668d280 0x7f0d6668d298            1-6 0 3   
(`k;;)
 0x7f0d6668d2a8     0x7f0d6668d2c0 0x7f0d6668d2d8 0x9d9350  1-6 4 1   `k
 0x7f0d6668d2a0     0x7f0d6668d040 0x7f0d6668d058            6-6 6 0   
 0x7f0d6668d298     0x7f0d6668d040 0x7f0d6668d058            6-6 6 0   
 0x7f0d6668d218     0x7f0d6668d380 0x7f0d6668d398            1-6 0 3   
(`t;-4.103904e+08;)
 0x7f0d6668d3a8     0x7f0d6668d3c0 0x7f0d6668d3d8 0x9d9370  1-6 4 1   `t
 0x7f0d6668d3a0     0x7f0d6668d300 0x7f0d6668d318            1-6 2 1   -4.103904e+08
 0x7f0d6668d398     0x7f0d6668d040 0x7f0d6668d058            6-6 6 0   
before
after

BEG denameRecurse      p: 0x7f0d6668d2a0      t:       create: 0      show(*p):     0x7f0d6668d040 0x7f0d6668d058            6-6 6 0   

BEG denameRecurse      p: 0x7f0d6668d2a0      t: _y      create: 0      show(*p):     0x7f0d6668d040 0x7f0d6668d058            6-6 6 0   
before
Segmentation fault (core dumped)
tavmem commented 2 years ago

Similarly, I changed show to sd_ in the 2nd commit of Sep 14, 2019 The result is:

[tom@localhost k190914b]$ rlwrap -n ./k
kona      \ for help. \\ to exit.

  {_y}

BEG denameRecurse      p: 0x44dda8      t: .k      create: 1      show(*p):     0x7f2f44df8200 0x7f2f44df8218            1-6 5 2   
.((`k;;)
  (`t;-4.103897e+08;))
 0x7f2f44df8220     0x7f2f44df8280 0x7f2f44df8298            1-6 0 3   
(`k;;)
 0x7f2f44df82a8     0x7f2f44df82c0 0x7f2f44df82d8 0x9f9350  1-6 4 1   `k
 0x7f2f44df82a0     0x7f2f44df8040 0x7f2f44df8058            6-6 6 0   
 0x7f2f44df8298     0x7f2f44df8040 0x7f2f44df8058            6-6 6 0   
 0x7f2f44df8218     0x7f2f44df8380 0x7f2f44df8398            1-6 0 3   
(`t;-4.103897e+08;)
 0x7f2f44df83a8     0x7f2f44df83c0 0x7f2f44df83d8 0x9f9370  1-6 4 1   `t
 0x7f2f44df83a0     0x7f2f44df8300 0x7f2f44df8318            1-6 2 1   -4.103897e+08
 0x7f2f44df8398     0x7f2f44df8040 0x7f2f44df8058            6-6 6 0   
before
after

BEG denameRecurse      p: 0x7f2f44df82a0      t:       create: 1      show(*p):     0x7f2f44df8040 0x7f2f44df8058            6-6 6 0   

BEG denameRecurse      p: 0x7ffe05c914e8      t: _y      create: 1      show(*p):     0x7f2f44df8800 0x7f2f44df8818            1-6 5 0   
.()
before

BEG denameRecurse      p: 0x44dda8      t: .k      create: 0      show(*p):     0x7f2f44df8200 0x7f2f44df8218            1-6 5 2   
.((`k;;)
  (`t;-4.103897e+08;))
 0x7f2f44df8220     0x7f2f44df8280 0x7f2f44df8298            1-6 0 3   
(`k;;)
 0x7f2f44df82a8     0x7f2f44df82c0 0x7f2f44df82d8 0x9f9350  1-6 4 1   `k
 0x7f2f44df82a0     0x7f2f44df8040 0x7f2f44df8058            6-6 6 0   
 0x7f2f44df8298     0x7f2f44df8040 0x7f2f44df8058            6-6 6 0   
 0x7f2f44df8218     0x7f2f44df8380 0x7f2f44df8398            1-6 0 3   
(`t;-4.103897e+08;)
 0x7f2f44df83a8     0x7f2f44df83c0 0x7f2f44df83d8 0x9f9370  1-6 4 1   `t
 0x7f2f44df83a0     0x7f2f44df8300 0x7f2f44df8318            1-6 2 1   -4.103897e+08
 0x7f2f44df8398     0x7f2f44df8040 0x7f2f44df8058            6-6 6 0   
before
after

BEG denameRecurse      p: 0x7f2f44df82a0      t:       create: 0      show(*p):     0x7f2f44df8040 0x7f2f44df8058            6-6 6 0   

BEG denameRecurse      p: 0x7f2f44df82a0      t: _y      create: 0      show(*p):     0x7f2f44df8040 0x7f2f44df8058            6-6 6 0   
before
{_y}
reserved error
>  

The results are identical to the current kona. Why is this significant? It shows that

The problem appears to be how the final output of denameRecurse is handled subsequently, causing the segfault.

gitonthescene commented 2 years ago

I’m hoping to get up to speed enough to pitch in more.

tavmem commented 2 years ago

You'll be fine. It take time.

The latest commit fixes the crash on {_y}, which was the first obective. However, this fix needs to be replaced by a more general fix, since {x _y}, {(x)_y}, {(x) _y} and, of course, {(0,x-!#x)_y[~x]} still cause crashes.