Skip to content
This repository has been archived by the owner on Jun 1, 2022. It is now read-only.

EtcTool crash #10

Open
spearx opened this issue Jan 10, 2017 · 3 comments
Open

EtcTool crash #10

spearx opened this issue Jan 10, 2017 · 3 comments

Comments

@spearx
Copy link

spearx commented Jan 10, 2017

Hi guys, sometimes i have a crash in the EtcTool.

I reviewed the code and i found a char array with a bad size.

In the EtcTool.cpp in function ProcessCommandLineArguments
if (pstrOutputFilename[c] == ETC_PATH_SLASH) { c++; ptrOutputDir = new char[c]; strncpy(ptrOutputDir, pstrOutputFilename, c); ptrOutputDir[c] = '\0'; CreateNewDir(ptrOutputDir); break; }

The ptrOutputDir variable has a bad size, the must be c+1, i changed my code to:

if (pstrOutputFilename[c] == ETC_PATH_SLASH) { c++; ptrOutputDir = new char[c+1]; strncpy(ptrOutputDir, pstrOutputFilename, c); ptrOutputDir[c] = '\0'; CreateNewDir(ptrOutputDir); break; }

And now all run right.

Thanks,

Ruben

@mainroach
Copy link
Contributor

Can you provide your input argument that causes the crash in ptrOutputDir ?

@jclee
Copy link

jclee commented Apr 5, 2017

For what it's worth, I'm encountering the same bug when running etctool under Ubuntu Precise. It's a memory error, so reproducing it in any given environment is probably going to be difficult. But in my specific case, I've observed the failure as a tripped malloc() assert for certain output path formats. For example, this output path containing a directory name of exactly 23 characters reproduces the crash for me, while directories of other lengths (tried 4-36) do not:

./etctool data/00007.png -output out_xxxxxxxxxxxxxxxxxxx/00007.ktx
etctool: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.

A gdb stacktrace shows the failure occurs in lodepng_realloc() at third_party/lodepng/lodepng.cpp:73, although I'm pretty sure there's nothing wrong with lodepng.cpp -- it's just fallout from the buffer overrun in EtcTool.cpp.

The corruption is reliably detected by valgrind for any input:

valgrind etctool data/00007.png -mipmaps 100 -format RGBA8 -effort 50 -output out/00007.ktx
[...]
      ==47421== Invalid write of size 1
      ==47421==    at 0x434BC6: Commands::ProcessCommandLineArguments(int, char const**) (EtcTool.cpp:656)
      ==47421==    by 0x4335D2: main (EtcTool.cpp:139)
      ==47421==  Address 0x5c3a178 is 0 bytes after a block of size 24 alloc'd
      ==47421==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==47421==    by 0x434B97: Commands::ProcessCommandLineArguments(int, char const**) (EtcTool.cpp:654)
      ==47421==    by 0x4335D2: main (EtcTool.cpp:139)
      ==47421== 
      ==47421== Invalid read of size 1
      ==47421==    at 0x58C0943: vfprintf (vfprintf.c:1661)
      ==47421==    by 0x58E58FA: vsprintf (iovsprintf.c:42)
      ==47421==    by 0x58C9506: sprintf (sprintf.c:32)
      ==47421==    by 0x435176: CreateNewDir(char const*) (EtcTool.cpp:821)
      ==47421==    by 0x434BD4: Commands::ProcessCommandLineArguments(int, char const**) (EtcTool.cpp:657)
      ==47421==    by 0x4335D2: main (EtcTool.cpp:139)
      ==47421==  Address 0x5c3a178 is 0 bytes after a block of size 24 alloc'd
      ==47421==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
      ==47421==    by 0x434B97: Commands::ProcessCommandLineArguments(int, char const**) (EtcTool.cpp:654)
      ==47421==    by 0x4335D2: main (EtcTool.cpp:139)
[...]

Per @spearx 's suggestion, I am able to fix both the valgrind output and the malloc assertion by expanding the buffer by one to accommodate the null terminator, on the following line:

https://github.com/google/etc2comp/blob/e2e733c/EtcTool/EtcTool.cpp#L654

@bonizz
Copy link

bonizz commented Apr 6, 2017

I agree with @spearx and @jclee, it looks like an off-by-one error.

The allocated size of the buffer is of size c, but ptrOutputDir[c] is one past the size of the buffer.
ptrOutputDir[c] = '\0'; writes a 0 past the allocated buffer.

Either ptrOutputDir[c-1] = '\0'; (to trim the trailing slash) or ptrOutputDir = new char[c+1]; should fix.

Edit: test case is to have an output file with a slash (dir separator) in it

bonizz added a commit to bonizz/etc2comp that referenced this issue Apr 6, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants