(command-line) cannot handle multi-byte command-line arguments
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Ikarus Scheme |
Fix Committed
|
High
|
Abdulaziz Ghuloum |
Bug Description
$ cat command-line
#!/usr/bin/env scheme-script
(import (rnrs))
(write (command-line)) (newline)
$ ./command-line λ # goes berserk
Unhandled exception:
Condition components:
1. &interrupted
2. &message: "received an interrupt signal"
$ ikarus -- λ
Ikarus Scheme version 0.0.3+ (revision 1579, build 2008-08-09)
Copyright (c) 2006-2008 Abdulaziz Ghuloum
> (command-line) ;; goes berserk
Unhandled exception:
Condition components:
1. &interrupted
2. &message: "received an interrupt signal"
$
Note the REPL did not reset, the ikarus process terminated.
I don't yet know why it's going berserk.
There's another issue I noticed that led me to discover the above:
ikarus-main.c, line 79:
this will transcode the command-line arguments as Latin-1. Instead, I suggest the command-line arguments be put in bytevectors and then in Scheme code the bytevectors are transcoded using (native-
Related branches
Changed in ikarus: | |
milestone: | none → 0.0.4 |
On Sat, 2008-08-09 at 20:05 +0000, Derick Eddington wrote:
> $ ikarus -- λ
> Ikarus Scheme version 0.0.3+ (revision 1579, build 2008-08-09)
> Copyright (c) 2006-2008 Abdulaziz Ghuloum
>
> > (command-line) ;; goes berserk
> Unhandled exception:
> Condition components:
> 1. &interrupted
> 2. &message: "received an interrupt signal"
> $
>
> Note the REPL did not reset, the ikarus process terminated.
>
> I don't yet know why it's going berserk.
It's going berserk because integer_ to_char( s[i]) returns a word with the
high bits set because s[i] is a char and integer_to_char casts it to
int, so for λ it's doing:
ce => ffffce0f
bb => ffffbb0f
When I make this change, it does not go berserk (but still transcodes as
Latin-1):
=== modified file 'src/ikarus-main.c' to_char( s[i])); to_char( (unsigned char)s[i])); alloc(pcb, pair_size);
--- src/ikarus-main.c 2008-08-09 12:47:44 +0000
+++ src/ikarus-main.c 2008-08-10 01:46:33 +0000
@@ -76,7 +76,7 @@
{
int i;
for(i=0; i<n; i++){
- string_set(str, i, integer_
+ string_set(str, i, integer_
}
}
ikptr p = ik_unsafe_
$ ./command-line λ
("./command-line" "Î\xBB;")
I didn't try to figure out if those high bits are revealing another bug
somewhere in Ikarus's character / string processing or if they are just
breaking an invariant.
Here's the strace of the berserking allocating a ton of memory:
execve( "/home/ d/bin/ikarus" , ["ikarus", "--r6rs-script", "command-line.sps", "\316\273"], [/* line.sps" , O_RDONLY) = 3 PROT_WRITE| PROT_EXEC, MAP_PRIVATE| MAP_ANONYMOUS, -1, 0) = 0xb75c2000 PROT_WRITE| PROT_EXEC, MAP_PRIVATE| MAP_ANONYMOUS, -1, 0) = 0xb71c2000 PROT_WRITE| PROT_EXEC, MAP_PRIVATE| MAP_ANONYMOUS, -1, 0) = 0xb6916000 PROT_WRITE| PROT_EXEC, MAP_PRIVATE| MAP_ANONYMOUS, -1, 0) = 0xb71bc000 PROT_WRITE| PROT_EXEC, MAP_PRIVATE| MAP_ANONYMOUS, -1, 0) = 0xb71b6000 PROT_WRITE| PROT_EXEC, MAP_PRIVATE| MAP_ANONYMOUS, -1, 0) = 0x84afa000 PROT_WRITE| PROT_EXEC, MAP_PRIVATE| MAP_ANONYMOUS, -1, 0) = 0xb70f4000 PROT_WRITE| PROT_EXEC, MAP_PRIVATE| MAP_ANONYMOUS, -1, 0) = 0x846fa000
[... start-up stuff ...]
open("command-
read(3, "(import (rnrs))\n(write (command-"..., 16384) = 49
read(3, "", 16384) = 0
close(3) = 0
mmap2(NULL, 4096, PROT_READ|
mmap2(NULL, 4194304, PROT_READ|
mmap2(NULL, 4194304, PROT_READ|
mmap2(NULL, 24576, PROT_READ|
munmap(0xb6ff8000, 20480) = 0
mmap2(NULL, 24576, PROT_READ|
munmap(0xb70c7000, 20480) = 0
[... much more ...]
mmap2(NULL, 843776, PROT_READ|
munmap(0x84fc8000, 835584) = 0
mmap2(NULL, 843776, PROT_READ|
munmap(0x8e787000, 835584) = 0
mmap2(NULL, 4194304, PROT_READ|
Also, this wasn't necessary to fix the berserking, and I don't
completely understand C casting, and I didn't look for other similar
casting spots, but it seems like these types should be something more
like this:
=== modified file 'src/ikarus-data.h'
--- src/ikarus-data.h 2008-07-20 07:14:09 +0000
+++ src/ikarus-data.h 2008-08-10 01:34:13 +0000
@@ -91,7 +91,7 @@
typedef unsigned long int ikptr;
-typedef int ikchar;
+typedef ikptr ikchar;
void ik_error(ik...