ueno/libskk

skk causes segfault on 64bit-FreeBSD

HirotoKagotani opened this issue · 4 comments

I installed libskk on FreeBSD-9.0/amd64 box.
When I run skk command with no argument, it causes a segfault.
Here is the backtrace and some variable dump using GDB.

(gdb) bt
#0  0x00000008014787d7 in g_type_fundamental ()
   from /usr/local/lib/libgobject-2.0.so.0
#1  0x0000000801463a67 in g_object_new ()
   from /usr/local/lib/libgobject-2.0.so.0
#2  0x000000080087dd08 in skk_rule_get_filter (self=0x802c0a740) at rule.c:1189
#3  0x0000000800884296 in skk_state_reset (self=0x802c70830) at state.c:1117
#4  0x0000000800883fbf in skk_state_construct (object_type=34406890944,
    dictionaries=0x802c6f1a0) at state.c:1024
#5  0x0000000800883ffd in skk_state_new (dictionaries=0x802c6f1a0)
    at state.c:1030
#6  0x000000080089035f in skk_context_construct (object_type=34406890368,
    dictionaries=0x802c18400, dictionaries_length1=1) at context.c:682
#7  0x00000008008904a3 in skk_context_new (dictionaries=0x802c18400,
    dictionaries_length1=1) at context.c:699
#8  0x00000000004037fb in _vala_main (args=0x7fffffffd350, args_length1=1)
    at skk.c:596
#9  0x0000000000403d60 in main (argc=1, argv=0x7fffffffd350) at skk.c:683
(gdb) frame 2
#2  0x000000080087dd08 in skk_rule_get_filter (self=0x802c0a740) at rule.c:1189
1189                    _tmp6_ = g_object_new (_tmp5_, NULL);
(gdb) list
1184                    _tmp2_ = self->priv->_metadata;
1185                    _tmp3_ = _tmp2_.filter;
1186                    _tmp4_ = gee_map_get (_tmp1_, _tmp3_);
1187                    type = GPOINTER_TO_INT (_tmp4_);
1188                    _tmp5_ = type;
1189                    _tmp6_ = g_object_new (_tmp5_, NULL);
1190                    _tmp7_ = G_IS_INITIALLY_UNOWNED (_tmp6_) ? g_object_ref_sink (_tmp6_) : _tmp6_;
1191                    _g_object_unref0 (self->priv->filter);
1192                    self->priv->filter = SKK_KEY_EVENT_FILTER (_tmp7_);
1193            }
(gdb) print _tmp4_
$1 = 0x802c95400
(gdb) print type
$2 = 46748672
(gdb) print sizeof _tmp4_
$3 = 8
(gdb) print sizeof type
$4 = 8
(gdb) print sizeof(int)
$5 = 4
(gdb) print sizeof(void*)
$6 = 8

From this, I realize type variable has the 32-bit truncated value produced by GPOINTER_TO_INT from _tmp4_.

This code gets SIGSEVG on 64-bit FreeBSD.

using Gee;

class Foo : Object {
}
class Bar {
  static Map<string,Type> map = new HashMap<string,Type> ();

  public static Object newobj() {
    var type1 = typeof (Foo);
    var obj1 = Object.new(type1); // succeed
    map.set ("foo", type1);

    var type2 = map.get("foo");
    var obj2 = Object.new(type2); // fail on 64-bit FreeBSD
    return obj2;
  }
}
static int main (string[] args) {
  var bar = new Bar();
  var obj = bar.newobj();
  return 0;
}

How about Linux distributions and other OSs?

ueno commented

I could reproduce this on OpenBSD amd64, and your guess seems right - on GNU/Linux, type IDs are normally smaller than sizeof(guint). I'll file a bug against vala compiler and prepare workaround.

ueno commented

Could you try a95245a ?

Works well. Thank you!