Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Out of bound memory write when disassembling some PPC instructions #1912

Closed
hamarituc opened this issue Aug 17, 2022 · 0 comments · Fixed by #2013
Closed

Out of bound memory write when disassembling some PPC instructions #1912

hamarituc opened this issue Aug 17, 2022 · 0 comments · Fixed by #2013

Comments

@hamarituc
Copy link
Contributor

Summary

When disassembling PowerPC code, an out of bound write occurs during register decoding, which corrupts the heap memory management.

Consider the following code.

#include <stdio.h>
#include <stdlib.h>

#include <capstone/platform.h>
#include <capstone/capstone.h>

int main()
{
  csh handle;
  unsigned char code[] = { 0x2d, 0x03, 0x00, 0x80 };
  cs_insn *insn;
  size_t count;

  cs_open(CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, &handle);
  cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME);
  cs_disasm(handle, code, sizeof(code) / sizeof(unsigned char), 0x1000, 0, &insn);
  cs_close(&handle);

  return 0;
}

Compile it.

$ gcc -g code.c -o /tmp/a.out -lcapstone

Actual behavior

When this code is run on an PPC64 host, it fails as follows (at least under Gentoo Linux):

free(): invalid pointer
Aborted

On other platforms the program might not fail, but the error exists as well.

Expected behavior

The program doesn't fail.

Additional context

The issue could be tracked down to function stripRegisterPrefix function with the following GDB session.

# gdb /tmp/a.out 
(gdb) break stripRegisterPrefix
Function "stripRegisterPrefix" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (stripRegisterPrefix) pending.
(gdb) run
Starting program: /tmp/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Breakpoint 1, stripRegisterPrefix (RegName=0x7ffff7b68977 <AsmStrs.3+311> "cr2") at /var/tmp/portage/dev-libs/capstone-5.0_rc2-r1/work/capstone-5.0-rc2/arch/PowerPC/PPCInstPrinter.c:1104
1104            switch (RegName[0]) {
(gdb) n
1114                            if (RegName[1] == 'r') {
(gdb) 
1116                                    char *name = cs_strdup(RegName + 2);
(gdb) 
1119                                    name[strlen(name) - 2] = '\0';
(gdb) print name
$1 = 0x55555555c3b0 "2"
(gdb) print (size_t)strlen(name)
$2 = 1

In line 1119 the last two characters of name are removed. But the string is only one character long. So the byte immediately before the start of the string (which is part of the Glibc internal heap data structure) is overwritten by \0.

This error was introduced in commit 30627ba.

The instruction triggering the bug is:

$ cstool ppc64be "2d030080"
 0  2d 03 00 80  cmpwi  cr2, r3, 0x80
hamarituc added a commit to hamarituc/capstone that referenced this issue Aug 22, 2022
hamarituc added a commit to hamarituc/capstone that referenced this issue Sep 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant