| Summary: | SDL_NewAudioStream() fails if calloc(0, xx) returns NULL | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Ozkan Sezer <sezeroz> |
| Component: | audio | Assignee: | Ryan C. Gordon <icculus> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | ||
| Version: | HG 2.0 | ||
| Hardware: | All | ||
| OS: | All | ||
| Attachments: | SDL_malloc patch | ||
Created attachment 2979 [details] SDL_malloc patch An alternative (possibly better?) soulution would be making sure that SDL_malloc(0) or SDL_calloc(0, x) doesn't return NULL, like below: (also attached). # HG changeset patch # User Ozkan Sezer <sezero@users.sourceforge.net> # Date 1507807685 -10800 # Thu Oct 12 14:28:05 2017 +0300 # Node ID bee06d420e14cadddfee53da5a8ff40508e9dfd5 # Parent 0f2de8f6c959f98264ac99869038a7999f96f5f0 make sure that SDL_malloc(0) or SDL_calloc(0,x) doesn't return NULL. diff --git a/src/stdlib/SDL_malloc.c b/src/stdlib/SDL_malloc.c --- a/src/stdlib/SDL_malloc.c +++ b/src/stdlib/SDL_malloc.c @@ -33,11 +33,17 @@ void *SDL_malloc(size_t size) { + if (!size) { + return malloc(1); + } return malloc(size); } void *SDL_calloc(size_t nmemb, size_t size) { + if (!size || !nmemb) { + return calloc(1,1); + } return calloc(nmemb, size); } I like the idea of making SDL_malloc() and friends have consistent zero size alloc behavior. https://hg.libsdl.org/SDL/rev/22fe56a64c6f Thanks! |
Since recent changes, I have been getting out of memory errors upon trying to initialize audio on OS/2. With the Dart implementation I am using, I am hitting (device->spec.samples != obtained->samples) in SDL_audio.c:open_audio_device() so it sets build_stream = SDL_TRUE and calls SDL_NewAudioStream(). SDL_audiocvt.c:ResamplerPadding() returns 0 because inrate == outrate, that results in SDL_calloc() returning NULL for retval->resampler_padding_samples which results in the failure return from SDL_NewAudioStream(). It is legal for malloc() or calloc() to return NULL for a 0 size arg, and obviously Watcom runtime does exactly that. I don't exactly know which particular changeset opened the way for this failure. I made a hack like below and it works for me (TM): --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -1260,6 +1260,7 @@ SDL_NewAudioStream(const SDL_AudioFormat const int packetlen = 4096; /* !!! FIXME: good enough for now. */ Uint8 pre_resample_channels; SDL_AudioStream *retval; + int nelem; /* for calloc() */ retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream)); if (!retval) { @@ -1285,7 +1286,11 @@ SDL_NewAudioStream(const SDL_AudioFormat retval->packetlen = packetlen; retval->rate_incr = ((double) dst_rate) / ((double) src_rate); retval->resampler_padding_samples = ResamplerPadding(retval->src_rate, retval->dst_rate) * pre_resample_channels; - retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples, sizeof (float)); + nelem = retval->resampler_padding_samples; + if (nelem == 0) { + nelem = 1; + } + retval->resampler_padding = (float *) SDL_calloc(nelem, sizeof (float)); if (retval->resampler_padding == NULL) { SDL_FreeAudioStream(retval); @@ -1313,7 +1318,7 @@ SDL_NewAudioStream(const SDL_AudioFormat #endif if (!retval->resampler_func) { - retval->resampler_state = SDL_calloc(retval->resampler_padding_samples, sizeof (float)); + retval->resampler_state = SDL_calloc(nelem, sizeof (float)); if (!retval->resampler_state) { SDL_FreeAudioStream(retval); SDL_OutOfMemory(); Of course there might be other ways of working around this, which I leave to you guys.