Skip to content

Commit

Permalink
Fixed crash when trying to load a sample set with a truncated wave file
Browse files Browse the repository at this point in the history
  • Loading branch information
oleg68 authored Nov 15, 2023
1 parent a09673e commit 8a8e13b
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
- Fixed crash when trying to load a sample set with a truncated wave file https://github.com/GrandOrgue/grandorgue/discussions/370
- Fixed crash on closing an organ https://github.com/GrandOrgue/grandorgue/issues/1678
# 3.13.1 (2023-11-05)
- Fixed the maximal value of the "SYSEX Hauptwerk 32 Byte LCD" midi send events https://github.com/GrandOrgue/grandorgue/issues/1686
Expand Down
48 changes: 36 additions & 12 deletions src/core/GOWave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,30 @@ void GOWave::Open(GOOpenedFile *file) {
Open(content, fileName);
}

static void check_for_bounds(
const wxString &fileName,
GO_WAVECHUNKHEADER *pHeader,
unsigned long offset,
unsigned long length,
unsigned long chunkOffset) {
unsigned long size = pHeader->dwSize;

if (offset + size > length) {
char buf[5];

strncpy(buf, (const char *)&pHeader->fccChunk, 4);
buf[4] = '\x00';
throw wxString::Format(
_("Malformed wave file '%s'. The chunk '%4s' at %lu with the size 8 + %lu"
" ends after the end of file %lu"),
fileName,
buf,
chunkOffset,
size,
length);
}
}

void GOWave::Open(const GOBuffer<uint8_t> &content, const wxString fileName) {
/* Close any currently open wave data */
Close();
Expand Down Expand Up @@ -197,6 +221,9 @@ void GOWave::Open(const GOBuffer<uint8_t> &content, const wxString fileName) {
/* Read chunk header */
GO_WAVECHUNKHEADER *header = (GO_WAVECHUNKHEADER *)(ptr + offset);
unsigned long size = header->dwSize;
unsigned long chunkOffset = offset;

// skip the header
offset += sizeof(GO_WAVECHUNKHEADER);

if (header->fccChunk == WAVE_TYPE_DATA) {
Expand All @@ -210,20 +237,25 @@ void GOWave::Open(const GOBuffer<uint8_t> &content, const wxString fileName) {
size = 0;
else {
m_SampleData.free();
check_for_bounds(fileName, header, offset, length, chunkOffset);
m_SampleData.Append(ptr + offset, size);
}
}
if (header->fccChunk == WAVE_TYPE_FMT) {
hasFormat = true;
check_for_bounds(fileName, header, offset, length, chunkOffset);
LoadFormatChunk(ptr + offset, size);
}
if (header->fccChunk == WAVE_TYPE_CUE) /* This used to only work if !load
m_pipe_percussive[i] */
if (header->fccChunk == WAVE_TYPE_CUE) { /* This used to only work if
!load m_pipe_percussive[i] */
check_for_bounds(fileName, header, offset, length, chunkOffset);
LoadCueChunk(ptr + offset, size);
if (header->fccChunk == WAVE_TYPE_SAMPLE) /* This used to only work if
}
if (header->fccChunk == WAVE_TYPE_SAMPLE) { /* This used to only work if
!load m_pipe_percussive[i] */
check_for_bounds(fileName, header, offset, length, chunkOffset);
LoadSamplerChunk(ptr + offset, size);

}
/* Move to next chunk respecting word alignment */
offset += size + (size & 1);
}
Expand All @@ -245,14 +277,6 @@ void GOWave::Open(const GOBuffer<uint8_t> &content, const wxString fileName) {
m_Loops.erase(m_Loops.begin() + i);
}
}
} catch (wxString msg) {
wxLogError(_("unhandled exception: %s\n"), msg);

/* Free any memory that was allocated by chunk loading procedures */
Close();

/* Rethrow the exception */
throw;
} catch (...) {
/* Free any memory that was allocated by chunk loading procedures */
Close();
Expand Down
7 changes: 5 additions & 2 deletions src/grandorgue/GOOrganController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,8 +573,11 @@ wxString GOOrganController::Load(
obj->GetLoadTitle(),
obj->GetLoadError());
}
errMsg.Printf(
_("There are errors while loading the organ. See Log Messages."));
GOMessageBox(
_("There are errors while loading the organ. See Log Messages."),
_("Load error"),
wxOK | wxICON_ERROR,
NULL);
} else {
if (objectDistributor.IsComplete())
m_Cacheable = true;
Expand Down
11 changes: 2 additions & 9 deletions src/grandorgue/model/GOSoundingPipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,19 +270,12 @@ void GOSoundingPipe::LoadData(
m_LoopCrossfadeLength,
m_ReleaseCrossfadeLength);
Validate();
} catch (wxString str) {
m_SoundProvider.ClearData();
throw wxString::Format(
_("Error while loading samples for rank %s pipe %s: %s"),
m_Rank->GetName().c_str(),
GetLoadTitle().c_str(),
str.c_str());
} catch (std::bad_alloc &ba) {
m_SoundProvider.ClearData();
throw GOOutOfMemory();
} catch (GOOutOfMemory e) {
} catch (...) {
m_SoundProvider.ClearData();
throw GOOutOfMemory();
throw;
}
}

Expand Down

0 comments on commit 8a8e13b

Please sign in to comment.