GNOME Bugzilla – Bug 779319
Register size hard-coded to zero in orc_x86_emit_*() functions causes SIGSEGV (x86)
Last modified: 2017-02-28 10:43:14 UTC
This bug (behavior?) was detected under GStreamer 1.10.3 and Orc 0.4.26 built for QNX 6.5.0 SP1 operating system. Maybe in other OSes it's masked by sprintf() or strlen() fuction, dunno. Steps to reproduce (at least at x86 platform with SSE support): 1) Build orc, GStreamer, gst-plugins-base with orc support. 2) Run gst-launch with videotestsrc (e.g. gst-launch videotestsrc ! fakesink): igor@irpc:~/PROJECTS$ ntox86-gdb /opt/gstreamer/x86/bin/gst-launch-1.0 ---cut--- (gdb) run videotestsrc ! fakesink Starting program: /opt/gstreamer/x86/bin/gst-launch-1.0 videotestsrc ! fakesink Setting pipeline to PAUSED ... Pipeline is PREROLLING ... [New pid 733225 tid 2] Program received signal SIGSEGV, Segmentation fault. [Switching to pid 733225 tid 2] 0xb0361298 in strlen () from /opt/qnx650/target/qnx6/x86/lib/libc.so.3 (gdb) sharedlibrary (gdb) bt
+ Trace 237192
What's inside OrcX86Insn structure (see backtrace line #4): (gdb) print *(OrcX86Insn*)0x812d2d0 $1 = {opcode_index = ORC_X86_push, opcode = 0xb88049b8, imm = 0, src = 37, dest = 37, size = 0, label = 0, type = 0, offset = 0, index_reg = 0, shift = 0, code_offset = 0} (NOTICE: size == 0) So, seems that the main cause of this bug is that OrcX86Insn structure for ORC_X86_push opcode has its 'size' field value set to zero. These fuctions (for some reason - i don't know if it's right or wrong because i'm not an expert in Orc at all) ignore 'size' argument and explicitly set opcode's size to 0. So they emit 'push' opcode to OrcCompiler's list with zero size: (orc/orcx86.c:127) void orc_x86_emit_push (OrcCompiler *compiler, int size, int reg) { orc_x86_emit_cpuinsn_size (compiler, ORC_X86_push, 0, reg, reg); } void orc_x86_emit_pop (OrcCompiler *compiler, int size, int reg) { orc_x86_emit_cpuinsn_size (compiler, ORC_X86_pop, 0, reg, reg); } But later, it's used here as an argument of orc_x86_get_regname_size() function (orc/orcx86insn.c:483): -------- cut ---------- case ORC_X86_INSN_TYPE_REGM_REG: case ORC_X86_INSN_TYPE_STACK: sprintf(op2_str, "%%%s", orc_x86_get_regname_size (xinsn->dest, xinsn->size)); break; -------- cut ---------- In this case, function orc_x86_get_regname_size() returns NULL and causes sprintf (at lease in QNX's libc) to cause SIGSEGV. My fix for this issue (no deep testing yet, but it seems reasonable and at least it works for me): void orc_x86_emit_push (OrcCompiler *compiler, int size, int reg) { /* orc_x86_emit_cpuinsn_size (compiler, ORC_X86_push, 0, reg, reg); */ orc_x86_emit_cpuinsn_size (compiler, ORC_X86_push, size, reg, reg); } void orc_x86_emit_pop (OrcCompiler *compiler, int size, int reg) { /* orc_x86_emit_cpuinsn_size (compiler, ORC_X86_pop, 0, reg, reg); */ orc_x86_emit_cpuinsn_size (compiler, ORC_X86_pop, size, reg, reg); } Regards, Igor.
Thanks for finding this. Does the testsuite work for you after this? Also would you mind providing a "git format-patch" style patch with an appropriate commit message and your name/mail address? :)
Sure, i'll check (right moment to start using testsuites :) If it'll pass, i'll prepare an appropriate patch. But, again, it's rather strange that this issue was dormant during such a long time and hasn't been detected earlier on other platforms (far more popular than QNX).
Created attachment 346892 [details] [review] proposed patch
I've checked it with 'make check' both in QNX 6.5.0 SP1 and Linux, no errors (10 of 10 passed).
Thanks for the patch! :) commit 249c709e90458ecef7a068df553ea41a83eedf0f Author: Igor Rondarev <igor.rondarev@gmail.com> Date: Tue Feb 28 12:23:55 2017 +0300 orcx86: Don't hard-code register size to zero in orc_x86_emit_*() functions Instead use the size passed as argument. Fixes segmentation fault on QNX. https://bugzilla.gnome.org/show_bug.cgi?id=779319