Skip to content

Commit

Permalink
Fix mbe play fn segfault (#1)
Browse files Browse the repository at this point in the history
* cmake: fix portaudio linking issue (szechyjs#103)

* Fixing multiple definitions of exitflag (szechyjs#104) (szechyjs#105)

Thanks to N0YKG for the fix! I am just making the PR :)

* Create codeql-analysis.yml

* Install deps

* Initialize last_dibit variable (szechyjs#119)

* Refactored dsd_mbe::playMbeFile to properly handle eof and closing the currently read file, which was causing segfaults for large numbers of mbe files being read in. Extracted reader function calls to typedefed pointer, s.t. since the file type only needs to be read per file, it could be set to a generic function pointer thus cleaning up the read loop. Fixed end conditions for both the while and for loops, s.t. they break on exit flag, and their respective conditions. Removed redundant cleanup function call since the caller calls it on return of the play function anyway.

* Added default case, and fixed while loop condition.

* Added a bunch of file helper functions to handle error checking.

* Added file open helper function. Refactored file error handler to be extensible beyond EOF being defined as -1 in glibc. Changed expected EOF in playMbeFile to be handled specially (i.e. not sent to error handler) because it's more likely than not to be expected, and in any case, we can just trying playing the next file.

* Made print in play function respect the quiet flag

* reverted CMakeLists change

* reverted CMakeLists change

* reverted CMakeLists change, I should've just used sed

---------

Co-authored-by: ra1nb0w <[email protected]>
Co-authored-by: Yinette Hodge <[email protected]>
Co-authored-by: Jared Szechy <[email protected]>
Co-authored-by: Clayton Smith <[email protected]>
  • Loading branch information
5 people authored Oct 3, 2023
1 parent 59423fa commit b972ed1
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 76 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@ dsd
*.dylib
build
.DS_Store
.idea
cmake-build*
*.swp

build/
9 changes: 7 additions & 2 deletions cmake/FindLibSndFile.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,10 @@ SET(LIBSNDFILE_NAMES ${LIBSNDFILE_NAMES} sndfile libsndfile)
FIND_LIBRARY(LIBSNDFILE_LIBRARY NAMES ${LIBSNDFILE_NAMES})

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LIBSNDFILE DEFAULT_MSG LIBSNDFILE_LIBRARY
LIBSNDFILE_INCLUDE_DIR)
if (APPLE)
find_package_handle_standard_args(LibSndFile DEFAULT_MSG LIBSNDFILE_LIBRARY
LIBSNDFILE_INCLUDE_DIR)
elseif (UNIX)
find_package_handle_standard_args(LIBSNDFILE DEFAULT_MSG LIBSNDFILE_LIBRARY
LIBSNDFILE_INCLUDE_DIR)
endif() #TODO elseif windows lol
3 changes: 2 additions & 1 deletion include/dsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,5 +316,6 @@ void processX2TDMAvoice (dsd_opts * opts, dsd_state * state);
void processDSTAR_HD (dsd_opts * opts, dsd_state * state);
short dmr_filter(short sample);
short nxdn_filter(short sample);

int checkFileError(FILE *file);
int handleFileError(char *fileName, int fileStatus);
#endif // DSD_H
94 changes: 67 additions & 27 deletions src/dsd_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,49 @@

#include "dsd.h"

static void openFile(FILE **file, char *fileName) {
char errorMsg[255];

*file = fopen(fileName, "ro");
if (NULL == *file) {
sprintf(errorMsg, "Error: could not open %s ", fileName);
perror(errorMsg);
exitflag = 1;
}
}

int checkFileError(FILE *file) {
if (ferror(file)) {
return 1;
} else if (feof(file)) {
return EOF;
}

return 0;
}

int handleFileError(char *fileName, int fileStatus) {

char errorMsg[255];

switch (fileStatus) {
case 0:
break;
case EOF:
sprintf(errorMsg, "Unexpected EOF when reading file %s ", fileName);
perror(errorMsg);
break;
case 1:
default:
sprintf(errorMsg, "I/O error when reading file %s ", fileName);
perror(errorMsg);
exitflag = 1;
break;
}

return fileStatus;
}

void
saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d)
{
Expand Down Expand Up @@ -130,38 +173,35 @@ readAmbe2450Data (dsd_opts * opts, dsd_state * state, char *ambe_d)
return (0);
}

void
openMbeInFile (dsd_opts * opts, dsd_state * state)
{
void openMbeInFile(dsd_opts *opts, dsd_state *state) {

char cookie[5];
char cookie[5];
int c, i;

opts->mbe_in_f = fopen (opts->mbe_in_file, "ro");
if (opts->mbe_in_f == NULL)
{
printf ("Error: could not open %s\n", opts->mbe_in_file);
}
openFile(&opts->mbe_in_f, opts->mbe_in_file);

// read cookie
cookie[0] = fgetc (opts->mbe_in_f);
cookie[1] = fgetc (opts->mbe_in_f);
cookie[2] = fgetc (opts->mbe_in_f);
cookie[3] = fgetc (opts->mbe_in_f);
cookie[4] = 0;
if (strstr (cookie, ".amb") != NULL)
{
state->mbe_file_type = 1;
}
else if (strstr (cookie, ".imb") != NULL)
{
state->mbe_file_type = 0;
for (i = 0; !exitflag && i < 4; ++i) {

c = fgetc(opts->mbe_in_f);

if (handleFileError(opts->mbe_in_file, checkFileError(opts->mbe_in_f))) {
break;
}

// read cookie
cookie[i] = (char) c;
}
else
{
state->mbe_file_type = -1;
printf ("Error - unrecognized file type\n");
cookie[4] = 0;

if (strstr(cookie, ".amb") != NULL) {
state->mbe_file_type = 1;
} else if (strstr(cookie, ".imb") != NULL) {
state->mbe_file_type = 0;
} else {
state->mbe_file_type = -1;
fprintf(stderr, "%s\n", "Error - unrecognized file type");
exitflag = 1;
}

}

void
Expand Down
130 changes: 84 additions & 46 deletions src/dsd_mbe.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,56 +17,94 @@

#include "dsd.h"

void
playMbeFiles (dsd_opts * opts, dsd_state * state, int argc, char **argv)
{
typedef void (*dataReaderDef)(dsd_opts *opts, dsd_state *state);

int i;
char imbe_d[88];
char ambe_d[49];
static void readImbe(dsd_opts *opts, dsd_state *state) {

for (i = state->optind; i < argc; i++)
{
sprintf (opts->mbe_in_file, "%s", argv[i]);
openMbeInFile (opts, state);
mbe_initMbeParms (state->cur_mp, state->prev_mp, state->prev_mp_enhanced);
printf ("playing %s\n", opts->mbe_in_file);
while (feof (opts->mbe_in_f) == 0)
{
if (state->mbe_file_type == 0)
{
readImbe4400Data (opts, state, imbe_d);
mbe_processImbe4400Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, imbe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
processAudio (opts, state);
if (opts->wav_out_f != NULL)
{
writeSynthesizedVoice (opts, state);
}

if (opts->audio_out == 1)
{
playSynthesizedVoice (opts, state);
}
}
else if (state->mbe_file_type == 1)
{
readAmbe2450Data (opts, state, ambe_d);
mbe_processAmbe2450Dataf (state->audio_out_temp_buf, &state->errs, &state->errs2, state->err_str, ambe_d, state->cur_mp, state->prev_mp, state->prev_mp_enhanced, opts->uvquality);
processAudio (opts, state);
if (opts->wav_out_f != NULL)
{
writeSynthesizedVoice (opts, state);
}
if (opts->audio_out == 1)
{
playSynthesizedVoice (opts, state);
}
}
if (exitflag == 1)
{
cleanupAndExit (opts, state);
char imbe_d[88];
readImbe4400Data(opts, state, imbe_d);
mbe_processImbe4400Dataf(state->audio_out_temp_buf,
&state->errs,
&state->errs2,
state->err_str,
imbe_d,
state->cur_mp,
state->prev_mp,
state->prev_mp_enhanced,
opts->uvquality);
}

static void readAmbe(dsd_opts *opts, dsd_state *state) {

char ambe_d[49];
readAmbe2450Data(opts, state, ambe_d);
mbe_processAmbe2450Dataf(state->audio_out_temp_buf,
&state->errs,
&state->errs2,
state->err_str,
ambe_d,
state->cur_mp,
state->prev_mp,
state->prev_mp_enhanced,
opts->uvquality);
}

static void playMbeFile(dataReaderDef readData, dsd_opts *opts, dsd_state *state) {

int ret;

while (!exitflag && readData != NULL) {

readData(opts, state);
processAudio(opts, state);

if (opts->wav_out_f != NULL) {
writeSynthesizedVoice(opts, state);
}

if (1 == opts->audio_out) {
playSynthesizedVoice(opts, state);
}

if ((ret = checkFileError(opts->mbe_in_f))) {

if (ret != EOF) {
handleFileError(opts->mbe_in_file, ret);
}
break;
}
}
}

void playMbeFiles(dsd_opts *opts, dsd_state *state, int argc, char **argv) {

int i;
for (i = state->optind; !exitflag && i < argc; i++) {

strcpy(opts->mbe_in_file, argv[i]);
openMbeInFile(opts, state);
mbe_initMbeParms(state->cur_mp,
state->prev_mp,
state->prev_mp_enhanced);

if (opts->verbose > 0) {
printf("playing %s\n", opts->mbe_in_file);
}

switch (state->mbe_file_type) {
case 0:
playMbeFile(readImbe, opts, state);
break;
case 1:
playMbeFile(readAmbe, opts, state);
break;
default:
fprintf(stderr, "Error - unrecognized file type %d\n", state->mbe_file_type);
exitflag = 1;
break;
}

handleFileError(opts->mbe_in_file, fclose(opts->mbe_in_f));
}
}

Expand Down

0 comments on commit b972ed1

Please sign in to comment.