|
From: Kristis M. <kri...@as...> - 2006-03-09 19:41:26
|
Hello, I've come across a case where libdisasm2 does not set the size of an invalid instruction properly. I'm using libdisasm2 from CVS as of 2005-08-31, using a patch I once submitted for not dropping invalid instructions (http://sourceforge.net/mailarchive/forum.php?thread_id=8094996&forum_id=36930) Here's what objdump reports: # objdump -D -b binary -m i386 image_invalid_opcode_c0.bin image_invalid_opcode_c0.bin: file format binary objdump: image_invalid_opcode_c0.bin: no symbols Disassembly of section .data: 00000000 <.data>: 0: 8c 10 movl %ss,(%eax) 2: 8c 10 movl %ss,(%eax) 4: 8c 10 movl %ss,(%eax) 6: c0 .byte 0xc0 0xc0 is an invalid instruction, but should still be reported by libdisasm2 as plain data. Here's what I get with libdisasm2: QUICKDIS Disassembly of .text: Intel syntax 0: 8c 10 mov [eax], ss 2: 8c 10 mov [eax], ss 4: 8c 10 mov [eax], ss invalid opcode FFFFFFC0 Adding an instruction of size zero Again, the motivation here is to apply special processing on a function image. If some instruction, or data in code, is interpreted as an invalid opcode and silently dropped, then the function size changes, and any special processing logic applied on it is thrown off. Plus, if this is data in code, some data is lost. I also tried this with the latest disasm2 from sourceforge and I get with x86dis: 00000000 8C 10 mov [eax], ss 00000002 8C 10 mov [eax], ss 00000004 8C 10 mov [eax], ss X86DIS ERROR 'Instruction at RVA extends beyond buffer:' 0x00000006 I was able to fix this problem with the patch that follows. This change has not broken any of my ~30 tests, but I don't know if it breaks anything else. Please apply. Thanks, Kristis =================================================================== --- x86_disasm.c 1 Sep 2005 04:11:55 -0000 1.1 +++ x86_disasm.c 9 Mar 2006 19:43:00 -0000 1.2 @@ -46,12 +46,8 @@ } /* check if we overran the end of the buffer */ - /* FIXME: this may no longer have an effect : move to main - * disasm routine */ - if ( size > len ) { - x86_report_error( report_insn_bounds, (char*)buf_rva + offset ); - return(0); - } + if ( size > len ) + size = len; /* fill rva, offset, and bytes fields of insn */ insn->addr = buf_rva + offset; |