Skip to content

Commit a722846

Browse files
whisper : guard null source in buffer loader read callback (#3982)
* whisper : guard null source in buffer loader read callback whisper_init_from_buffer_with_params_no_state installs a read callback that copies from buf->buffer + current_offset. When the buffer is exhausted (or the supplied buffer is empty), size_to_copy is 0 and the source pointer can be null; passing a null pointer to memcpy is undefined behavior even for a zero-length copy (UBSan: 'null pointer passed as argument 2' at the memcpy). Loading a crafted/short model through the buffer loader could hit this. Skip the memcpy when there is nothing to copy. Loading from a null/empty or truncated buffer now fails gracefully (returns NULL) with no UB. This addresses bug 1 of #3879. Bug 2 (integer overflow when sizing the mel filter buffer) is covered by the open PR #3780. * fixup! whisper : guard null source in buffer loader read callback --------- Co-authored-by: Ben Younes <2910651+ousamabenyounes@users.noreply.github.com>
1 parent c122757 commit a722846

4 files changed

Lines changed: 37 additions & 3 deletions

File tree

src/parakeet.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3109,7 +3109,9 @@ struct parakeet_context * parakeet_init_from_buffer_with_params_no_state(void *
31093109

31103110
size_t size_to_copy = buf->current_offset + read_size < buf->size ? read_size : buf->size - buf->current_offset;
31113111

3112-
memcpy(output, buf->buffer + buf->current_offset, size_to_copy);
3112+
if (size_to_copy > 0 && buf->buffer != nullptr) {
3113+
memcpy(output, buf->buffer + buf->current_offset, size_to_copy);
3114+
}
31133115
buf->current_offset += size_to_copy;
31143116

31153117
return size_to_copy;

src/whisper.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3766,7 +3766,9 @@ struct whisper_context * whisper_init_from_buffer_with_params_no_state(void * bu
37663766

37673767
size_t size_to_copy = buf->current_offset + read_size < buf->size ? read_size : buf->size - buf->current_offset;
37683768

3769-
memcpy(output, buf->buffer + buf->current_offset, size_to_copy);
3769+
if (size_to_copy > 0 && buf->buffer != nullptr) {
3770+
memcpy(output, buf->buffer + buf->current_offset, size_to_copy);
3771+
}
37703772
buf->current_offset += size_to_copy;
37713773

37723774
return size_to_copy;

tests/CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ target_link_libraries(${UTF8_TEST} PRIVATE common)
9696
add_test(NAME ${UTF8_TEST} COMMAND ${UTF8_TEST})
9797
set_tests_properties(${UTF8_TEST} PROPERTIES LABELS "unit")
9898

99+
set(BUFFER_LOADER_TEST test-whisper-buffer-loader)
100+
add_executable(${BUFFER_LOADER_TEST} ${BUFFER_LOADER_TEST}.cpp)
101+
target_include_directories(${BUFFER_LOADER_TEST} PRIVATE ../include ../ggml/include ../examples)
102+
target_link_libraries(${BUFFER_LOADER_TEST} PRIVATE common)
103+
add_test(NAME ${BUFFER_LOADER_TEST} COMMAND ${BUFFER_LOADER_TEST})
104+
set_tests_properties(${BUFFER_LOADER_TEST} PROPERTIES LABELS "unit;gh")
105+
99106
# VAD test tests VAD in isolation
100107
set(VAD_TEST test-vad)
101108
add_executable(${VAD_TEST} ${VAD_TEST}.cpp)
@@ -177,4 +184,3 @@ add_parakeet_transcription_test(
177184
samples/diffusion2023-07-03.flac
178185
tests/parakeet-expected-diffusion-output.txt
179186
0.95)
180-
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "whisper.h"
2+
3+
#include <cstdint>
4+
#include <cstdio>
5+
6+
#ifdef NDEBUG
7+
#undef NDEBUG
8+
#endif
9+
#include <cassert>
10+
11+
int main() {
12+
struct whisper_context_params cparams = whisper_context_default_params();
13+
cparams.use_gpu = false;
14+
15+
struct whisper_context * ctx_empty = whisper_init_from_buffer_with_params(nullptr, 1, cparams);
16+
assert(ctx_empty == nullptr);
17+
18+
uint8_t truncated[8] = { 0 };
19+
struct whisper_context * ctx_trunc = whisper_init_from_buffer_with_params(truncated, sizeof(truncated), cparams);
20+
assert(ctx_trunc == nullptr);
21+
22+
printf("test-whisper-buffer-loader: OK\n");
23+
return 0;
24+
}

0 commit comments

Comments
 (0)