ksh: Memory/Segmentation fault for Justified Strings (-L/R/Z)

On Intel 64bit Linux/macOS, I encounter memory or segmentation faults when attempting to create or apply justification to strings with field width of large sizes. These faults also occur even if the justification is applied successfully upon variable assignment. However on an ARM 32bit Ubuntu machine, I can successfully create a string with an assignment up to its maximum allowable field width of 32767 aka (1<<15)-1 and these faults do not occur in my limited testing. But attempting to create the same assignment on a Ubuntu/macOS 64bit platform fails with a memory/segmentation faults. The Ubuntu almost always crashes out using (1<<15)-1 field width but the macOS may allow me to create up to (1<<24). All fail using (1<<30)–be warned that is requesting roughly 1GB of memory. To my knowledge, the maximum allowed fidth width on 64bit OSes should be (1<<31)-1 as 1<<31 makes the int32 size variable become negative in which case the negative field size error occurs.

ARM 32bit Ubuntu

$ typeset -L $((1<<15)) s=h
arch/linux.arm/bin/ksh: typeset: option argument cannot be greater than 32767
$ typeset -L $(((1<<15)-1)) s=h
$ typeset +p s                
typeset -L 32767 s
$ 

Ubuntu 64bit

$ arch/linux.i386-64/bin/ksh
$ typeset -L $(((1<<15)-1)) s=h
Segmentation fault (core dumped)

macOS

$ typeset -L $(((1<<15)-1)) s=h
$ typeset +p s
typeset -L 32767 s
$ typeset -L $(((1<<16)-1)) s=h
$ typeset +p s
typeset -L 65535 s
$ typeset -L $(((1<<17)-1)) s=h
$ typeset +p s
typeset -L 131071 s
$ typeset -L $(((1<<18)-1)) s=h
Memory fault

I found the following lines to be suspect as the length of size requested may be more then 7 greater than the original length of the value of the variable. https://github.com/ksh93/ksh/blob/6697edba1c302c4bdd0796945158decc825b5bd5/src/cmd/ksh93/sh/name.c#L2995-L3000

So, I altered the 1 line malloc code to the following with better results but memory crashes still happen when attempting to alter the variable’s value with a subsequent statement.

n=strlen(sp);
cp = (char*)malloc((n >= (unsigned)size ? n : (unsigned)size) + 1);

Not really sure why the authors added 8 instead of 1 to the length but during my testing it did not matter when the length was large enough to fit the request. I can only guess that is was some small attempt to provide a little buffer or room for something. As I see it, it is a waste of memory. And as such, so is selecting the larger of the two lenghs (n or size) as we could be shrinking the variable’s length. See below for my updated code to hopefully properly handle the initial memory allocation for field size.

n=strlen(sp);
if (size==0 || (newatts&(NV_INTEGER|NV_BINARY)))
{       // allocate to match existing value for numerics and auto length assignment for -L/R/Z
        cp = (char*)malloc(n + 1);
        strcpy(cp, sp);
}
else if(size>=n)
{       // growing string
        cp = (char*)malloc((unsigned)size + 1);
        strcpy(cp, sp);
}
else
{       // shrinking string
        cp = (char*)malloc((unsigned)size + 1);
        if(newatts&NV_RJUST)
		strncpy(cp, (n-size+sp), size);
 	else
       {       //NV_LJUST and the rest
               if(newatts&NV_ZFILL) // Skip over leading 0s 
			while(*sp=='0') sp++;
		strncpy(cp, sp, size);
       }
}

By using the above sizing code, I can fully create and reassign variables at will using the full typeset command with variable value assignment. Still, if I attempt to just do a plain value assignment to the variable afterwards, ksh crashes. If however, I use a typeset statement to alter the justification attributes to a small number (typeset -L 4 s) then make a s=abc statement; it works.

There be more gremlins.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 31

Commits related to this issue

Most upvoted comments

I can’t figure out a fix that works, so I’ll just revert 0e4c4d6 for now, as the bug it introduced is much worse than the one it fixed. I’ll add your reproducer as a regression test. I hope we’ll manage to find a fix for the TODOs reintroduced by the revert sometime, but it’s not a high priority.

Yes, I am now able to make an assignment without it crashing by using that diff above.