NBickford-NV / stb

stb single-file public domain libraries for C/C++

Home Page:https://twitter.com/nothings

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

stb_vorbis doesn't build as C++

DanielGibson opened this issue · comments

So far stb_vorbis.c could be built as C++ (I usually rename it to stb_vorbis.h and use it more or less like the other stb libs).
With the changes in this repo that doesn't work anymore

I haven't tried with MSVC, but GCC (g++) gives errors like this:

dhewm3/neo/sound/stb_vorbis.h:3790:54: error: cannot convert ‘uint8*’ {aka ‘unsigned char*’} to ‘void**’
 3790 |                    if (c->sparse) setup_temp_free(f, lengths, c->entries);
      |                                                      ^~~~~~~
      |                                                      |
      |                                                      uint8* {aka unsigned char*}
In file included from dhewm3/neo/sound/snd_decoder.cpp:36:
dhewm3/neo/sound/stb_vorbis.h:990:45: note:   initializing argument 2 of ‘void setup_temp_free(vorb*, void**, int)’
  990 | static void setup_temp_free(vorb *f, void **_p, int sz)
      |                                      ~~~~~~~^~

This happens in several other places where setup_temp_free() is called, and the issue is always that a uint8 * value is passed as second argument of setup_temp_free() which expects a void **.

I'm not sure how this code can work anywhere (even when compiled as C, which might be more tolerant with the implicit conversion) - uint8 * lengths gets the return value of setup_temp_malloc(whatever) assigned - and as far as I understand, those results are supposed to be passed dereferenced to setup_temp_free(), so setup_temp_free() can set the pointer to NULL (void *p = *_p; *_p = NULL;). So the example shown above should probably look like if (c->sparse) setup_temp_free(f, &lengths, c->entries);.

Changing the code to make the compiler happy would be easy enough, but TBH with errors like this I don't trust the changes that changed setup_temp_free() to take a pointer to a pointer enough to use them at all, and I don't have the time to review them thoroughly enough to figure out why this code apparently worked for whoever wrote it, despite appearing to be plainly wrong.

Update: Oh by the way, thanks a lot for maintaining this repo! :)

Oh, looking at git blame, the problem seems to be that the PR introducing the void ** argument (commit 2ec4a48) was independent of the one adding the setup_temp_free() calls in question (commit 684ae83) - that explains how this happened, of course.

Still makes me a bit weary of how well all these fixes merged together interact with each other..

Thank you for the issue! I'll put in a fix right now, and add some testing to make sure everything builds.

Awesome, thanks!
This fork might be useful: https://github.com/sezero/stb/tree/stb_vorbis-sezero
It contains lots of vorbis tests

Thank you! I think I've got a fix for it in 2e9cec9 . That fork's perfect; I'm going to see if I can import its tests and run through all of those and add a simple vorbis fuzzer before closing this issue.

On the testing side, I've added a CMake project with an initial go at building the various projects in tests/; that currently targets the top-level files in tests/, and I'm hoping to add the ones within subfolders as well.

That wound up finding a couple of issues, which I think I've fixed in 5ebf39c. The biggest one is that a line like

stbsp_snprintf(buf, 0, "7 chars");

would make stb_sprintf write a null terminator to buf[-1].

The other issue is that stb_c_lexer_fuzzer.c pretty much immediately finds a crash (a file that consists entirely of an identifier will make it read past the end). That's not good.

As of ca527d1, this fork now has the tests from sezero's fork, and a vorbis fuzzer!

Good news:

  • The fuzzer immediately found an error I made in 2e9cec9
  • sezero's tests found a couple of UBSan issues I hadn't merged in fixes for! I've imported those fixes from their branch, although I went with a different fix for https://github.com/sezero/stb/blob/stb_vorbis-sezero/stb_vorbis.c#L3922, throwing an error instead of performing the overflowing multiplication on unsigned integers.
    Bad news:
  • The fuzzer found a file that causes OOM following what rygorous described in nothings#937. I've made #2 to track implementing a fix for this.

I'm going to go ahead and close this issue, since I think the original issue (compilation) has now been fixed. Thanks again for reporting this!

Great work, thank you! :)