Subject: Invalid read access of chars of wide string in scm_seed_to_random_state

From: Tom de Vries <[email-masked]>
Date: Mon, 15 Oct 2018 10:44:58 +0200

Hi,

Consider min.c:
...
#include <locale.h>
#include "libguile.h"

static void *
foo (void *data)
{
  return NULL;
}

int
main (void)
{
  const char *msg = setlocale (LC_CTYPE, "ja_JP.sjis");
  printf ("msg: %s\n", msg);
  scm_with_guile (foo, NULL);
  return 0;
}
...

Compiled with guile-2.2.4:
...
$ gcc min.c -I /home/vries/guile/tarball/guile-2.2.4 -lguile-2.2 -L
/home/vries/guile/tarball/guile-2.2.4/libguile/.libs
-Wl,-rpath=/home/vries/guile/tarball/guile-2.2.4/libguile/.libs -g
...

We run into a segfault:
...
$ ./a.out
msg: ja_JP.sjis
Segmentation fault (core dumped)
...

The backtrace as reported by gdb is:
...
#0  0x00007ffff7b649ba in scm_variable_ref (var=0x0) at variable.c:92
#1  0x00007ffff7b63868 in scm_throw (key=key@entry=0x7a9580,
args=0x7b94c0) at throw.c:266
#2  0x00007ffff7b63e15 in scm_ithrow (key=key@entry=0x7a9580,
args=<optimized out>, no_return=no_return@entry=1)
    at throw.c:611
#3  0x00007ffff7af51a5 in scm_error_scm (key=key@entry=0x7a9580,
subr=<optimized out>,
    message=message@entry=0x7ba8e0, args=args@entry=0x7b9500,
data=data@entry=0x4) at error.c:94
#4  0x00007ffff7af525f in scm_error (key=0x7a9580, subr=subr@entry=0x0,
    message=message@entry=0x7ffff7b93358 "Invalid read access of chars
of wide string: ~s", args=0x7b9500,
    rest=rest@entry=0x4) at error.c:59
#5  0x00007ffff7af5642 in scm_misc_error (subr=subr@entry=0x0,
    message=message@entry=0x7ffff7b93358 "Invalid read access of chars
of wide string: ~s", args=<optimized out>)
    at error.c:299
#6  0x00007ffff7b5aa9a in scm_i_string_chars (str=<optimized out>,
str@entry=0x7ba900) at strings.c:571
#7  0x00007ffff7b3cef8 in scm_seed_to_random_state (seed=0x7ba900) at
random.c:444
#8  0x00007ffff7b3ddaa in scm_init_random () at ../libguile/random.x:3
#9  0x00007ffff7b0eb41 in scm_i_init_guile (base=<optimized out>) at
init.c:451
#10 0x00007ffff7b62128 in scm_i_init_thread_for_guile
(base=0x7fffffffdb10, dynamic_state=0x0) at threads.c:586
#11 0x00007ffff7b62159 in with_guile (base=0x7fffffffdb10,
data=0x7fffffffdb40) at threads.c:654
#12 0x00007ffff73a84a5 in GC_call_with_stack_base () from
/usr/lib64/libgc.so.1
#13 0x00007ffff7b624a8 in scm_i_with_guile (dynamic_state=<optimized
out>, data=<optimized out>,
    func=<optimized out>) at threads.c:704
#14 scm_with_guile (func=<optimized out>, data=<optimized out>) at
threads.c:710
#15 0x0000000000400786 in main () at min.c:15
...

We see that the backtrace happens while handling an "Invalid read access
of chars of wide string: ~s" error here:
...
const char *
scm_i_string_chars (SCM str)
{
  SCM buf;
  size_t start;
  get_str_buf_start (&str, &buf, &start);
  if (scm_i_is_narrow_string (str))
    return (const char *) STRINGBUF_CHARS (buf) + start;
  else
    scm_misc_error (NULL, "Invalid read access of chars of wide string: ~s",
                    scm_list_1 (str));
  return NULL;
}
...

What triggers the error is that here, we create a non-narrow string
using scm_from_locale_string:
...
#8  0x00007ffff7b3ddaa in scm_init_random () at ../libguile/random.x:3
3       scm_var_random_state = scm_c_define ("*random-state*",
scm_seed_to_random_state (scm_from_locale_string
("URL:http://stat.fsu.edu/~geo/diehard.html")));;
...

but then in scm_seed_to_random_state handle it like a narrow string by
calling scm_i_string_chars:
...
#define FUNC_NAME s_scm_seed_to_random_state
{
  SCM res;
  if (SCM_NUMBERP (seed))
    seed = scm_number_to_string (seed, SCM_UNDEFINED);
  SCM_VALIDATE_STRING (1, seed);
  res = make_rstate (scm_c_make_rstate (scm_i_string_chars (seed),
                                        scm_i_string_length (seed)));
  scm_remember_upto_here_1 (seed);
  return res;

}
...

Thanks,
- Tom