diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9003f5042b8581c54a52487a0e179b1594da38d8..3cc6086351b58d75e21acfa1f7ff6806fc830e7a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -544,81 +544,68 @@ renderer-smoke-test: junit: - report-junit.xml -# test renderer executable with cmake + asan -renderer-asan: +.renderer-sanitizer-job: extends: - .test-job-linux - .rules-merge-request-to-main needs: ["build-codec-linux-cmake"] stage: test - script: - - cmake -B cmake-build -G "Unix Makefiles" -DCLANG=asan -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true - - cmake --build cmake-build -- -j - - testcase_timeout=180 - - python3 -m pytest -q -n auto -rA --junit-xml=report-junit.xml tests/renderer/test_renderer.py --testcase_timeout=$testcase_timeout - + timeout: "30 minutes" artifacts: name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" expire_in: 1 week when: always paths: - report-junit.xml - expose_as: "renderer asan pytest results" + - report.html reports: junit: - report-junit.xml + before_script: + - cmake -B cmake-build -G "Unix Makefiles" -DCLANG=$SANITIZER_BUILD_STRING -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true + - cmake --build cmake-build -- -j + # rename files to fit naming convention + # en- and decoder needed because of split rendering testcases + - mv IVAS_cod IVAS_cod_ref + - mv IVAS_dec IVAS_dec_ref + - mv IVAS_rend IVAS_rend_ref + - testcase_timeout=180 + +# test renderer executable with cmake + asan +renderer-asan: + extends: + - .renderer-sanitizer-job + variables: + SANITIZER_BUILD_STRING: "asan" + script: + - python3 -m pytest -q --tb=no -n auto --html=report.html --self-contained-html --junit-xml=report-junit.xml tests/renderer/test_renderer.py tests/split_rendering/test_split_rendering.py --create_ref --testcase_timeout=$testcase_timeout + artifacts: + expose_as: "renderer asan result" + # test renderer executable with cmake + msan renderer-msan: extends: - - .test-job-linux - - .rules-merge-request-to-main - needs: ["build-codec-linux-cmake"] - stage: test + - .renderer-sanitizer-job + variables: + SANITIZER_BUILD_STRING: "msan" script: - - cmake -B cmake-build -G "Unix Makefiles" -DCLANG=msan -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true - - cmake --build cmake-build -- -j - - testcase_timeout=180 - - python3 -m pytest -q -n auto -rA --junit-xml=report-junit.xml tests/renderer/test_renderer.py --testcase_timeout=$testcase_timeout - + - python3 -m pytest -q --tb=no -n auto --html=report.html --self-contained-html --junit-xml=report-junit.xml tests/renderer/test_renderer.py tests/split_rendering/test_split_rendering.py --create_ref --testcase_timeout=$testcase_timeout artifacts: - name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" - expire_in: 1 week - when: always - paths: - - report-junit.xml - expose_as: "renderer msan pytest results" - reports: - junit: - - report-junit.xml + expose_as: "renderer msan result" + # test renderer executable with cmake + usan renderer-usan: extends: - - .test-job-linux - - .rules-merge-request-to-main - needs: ["build-codec-linux-cmake"] - stage: test + - .renderer-sanitizer-job + variables: + SANITIZER_BUILD_STRING: "usan" script: - - cmake -B cmake-build -G "Unix Makefiles" -DCLANG=usan -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true - - cmake --build cmake-build -- -j - - testcase_timeout=180 - - UBSAN_OPTIONS=suppressions=scripts/ubsan.supp,report_error_type=1,log_path=usan_log_catchall python3 -m pytest -q -n auto -rA --junit-xml=report-junit.xml tests/renderer/test_renderer.py --testcase_timeout=$testcase_timeout - - grep_exit_code=0 - - touch usan_log_empty # Creates an empty file, this is to avoid "grep: usan_log_*: No such file or directory" in case no USAN failures are reported from pytest - - grep UndefinedBehaviorSanitizer usan_log_* || grep_exit_code=$? - - if [ $grep_exit_code != 1 ] ; then echo "Run errors in test_renderer.py with Clang undefined-behavior-sanitizer"; exit 1; fi - + - UBSAN_OPTIONS=suppressions=scripts/ubsan.supp,report_error_type=1 python3 -m pytest -q --tb=no -n auto --html=report.html --self-contained-html --junit-xml=report-junit.xml tests/renderer/test_renderer.py tests/split_rendering/test_split_rendering.py --create_ref --testcase_timeout=$testcase_timeout artifacts: - name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" - expire_in: 1 week - when: always - paths: - - report-junit.xml - expose_as: "renderer usan pytest results" - reports: - junit: - - report-junit.xml + expose_as: "renderer usan result" + # compare renderer bitexactness between target and source branch renderer-pytest-on-merge-request: diff --git a/lib_com/options.h b/lib_com/options.h index 7745853825673f115ecb693bce6854061c460a56..a9f49183cf916eb8b787e2b2ca8d12defbb0fe0a 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -163,7 +163,7 @@ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ #define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ #define FIX_938_COMPILER_WARNING /* FhG: Fix compiler warning in ivas_mdct_core_reconstruct() */ - +#define FIX_1288_SPLIT_REND_XSAN /* Dlb: Fix asan, msan and usan issues in split rendering mode*/ /* #################### End BE switches ################################## */ diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 7b4b631f4075e0d0f0ecc53b1c478a17ae72c819..b3d7e62e92ee9d4b83d952e7104dd93781eb9b02 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -2782,8 +2782,11 @@ void ivas_destroy_dec( ivas_dirac_dec_close_binaural_data( st_ivas->hDiracDecBin ); /* Crend handle */ +#ifndef FIX_1288_SPLIT_REND_XSAN ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ), ( st_ivas->hSplitBinRend == NULL ) ? 1 : st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); - +#else + ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ) ); +#endif /* Reverb handle */ ivas_reverb_close( &st_ivas->hReverb ); diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index 7472690650963f06c709a1ae643c6556af5abf18..e18a28281aa698abdf84223e948fd541ac72a5f6 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -253,7 +253,11 @@ static ivas_error ivas_ism_bitrate_switching_dec( } /* close the crend binaural renderer */ +#ifndef FIX_1288_SPLIT_REND_XSAN ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ), ( st_ivas->hSplitBinRend == NULL ) ? 1 : st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); +#else + ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ) ); +#endif } } diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 6d406fccc1b3961b9c01a534b6a021f6c5dae36c..e15b9c437f6dae18e7840aa70a57ceaeca9ccb85 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -1169,7 +1169,11 @@ static ivas_error ivas_mc_dec_reconfig( if ( ( st_ivas->hCrendWrapper != NULL ) && ( st_ivas->hCrendWrapper->hCrend[0] != NULL ) && ( st_ivas->renderer_type != RENDERER_BINAURAL_MIXER_CONV && st_ivas->renderer_type != RENDERER_BINAURAL_MIXER_CONV_ROOM && ( st_ivas->renderer_type != RENDERER_BINAURAL_OBJECTS_TD || st_ivas->hIntSetup.output_config != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) { +#ifndef FIX_1288_SPLIT_REND_XSAN ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ), ( st_ivas->hSplitBinRend == NULL ) ? 1 : st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); +#else + ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ) ); +#endif } if ( st_ivas->hBinRendererTd != NULL && ( st_ivas->renderer_type != RENDERER_BINAURAL_OBJECTS_TD ) ) diff --git a/lib_lc3plus/ari_codec.c b/lib_lc3plus/ari_codec.c index 5ba87a32bc3b07eeeb825fe2cb6c6271ec9db0a3..2a76ecac8338b848957fd73b96f480d930038317 100644 --- a/lib_lc3plus/ari_codec.c +++ b/lib_lc3plus/ari_codec.c @@ -705,7 +705,7 @@ void ac_shift_fl(Encoder_State_fl* st) st->carry_count = st->carry_count + 1; } - st->low = st->low << 8; + st->low = (LC3_INT)((LC3_UINT32)st->low << 8); st->low = (st->low) & (16777215); /* 2^24 - 1 */ } diff --git a/lib_lc3plus/lc3.c b/lib_lc3plus/lc3.c index 56a39286f84a23ee09d244e0bc5fd057ba248b08..b275ed8084fc1b1caa5cce48e6ef18db7fa1af86 100644 --- a/lib_lc3plus/lc3.c +++ b/lib_lc3plus/lc3.c @@ -88,9 +88,9 @@ static int null_in_list(void **list, int n) /* return pointer to aligned base + base_size, *base_size += size + 4 bytes align */ void *balloc(void *base, size_t *base_size, size_t size) { - uintptr_t ptr = ((uintptr_t)base + *base_size + 3) & ~3; + uintptr_t ptr = ((uintptr_t)base + *base_size + 3) & (uintptr_t)(~3); assert((uintptr_t)base % 4 == 0); /* base must be 4-byte aligned */ - *base_size = (*base_size + size + 3) & ~3; + *base_size = (*base_size + size + 3) & (uintptr_t)(~3); return (void *)ptr; } diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index 8455901f4d0d9642ba1a05221c19ca14e40640ef..322d6b7e223a0ec3e3ab993b4eae666790b37384 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -1076,6 +1076,13 @@ ivas_error ivas_rend_initCrendWrapper( ( *pCrend )->binaural_latency_ns = 0; ( *pCrend )->hHrtfCrend = NULL; +#ifdef FIX_1288_SPLIT_REND_XSAN + for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + ( *pCrend )->hCrend[pos_idx] = NULL; + } +#endif + for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) { hCrend = NULL; @@ -1338,10 +1345,14 @@ ivas_error ivas_rend_openCrend( * * Deallocate Crend renderer handle *------------------------------------------------------------------------*/ - +#ifndef FIX_1288_SPLIT_REND_XSAN void ivas_rend_closeCrend( CREND_WRAPPER_HANDLE *pCrend, const int16_t num_poses ) +#else +void ivas_rend_closeCrend( + CREND_WRAPPER_HANDLE *pCrend ) +#endif { int16_t i; int16_t pos_idx; @@ -1357,7 +1368,11 @@ void ivas_rend_closeCrend( ivas_hrtf_close( &( *pCrend )->hHrtfCrend ); } +#ifndef FIX_1288_SPLIT_REND_XSAN for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) +#else + for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) +#endif { hCrend = ( *pCrend )->hCrend[pos_idx]; if ( hCrend != NULL ) diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 121d9128816dc8b855b84e580eb5d872ccf9a1d9..0e17d68ed0f51d1b87f0804cb2b2f5016ea3cc2c 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -903,10 +903,15 @@ ivas_error ivas_rend_openCrend( const int16_t num_poses ); +#ifndef FIX_1288_SPLIT_REND_XSAN void ivas_rend_closeCrend( CREND_WRAPPER_HANDLE *pCrend, const int16_t num_poses ); +#else +void ivas_rend_closeCrend( + CREND_WRAPPER_HANDLE *pCrend ); +#endif ivas_error ivas_Crend_hrtf_init( HRTFS_CREND_DATA *hHrtf /* i/o: Crend HRTF handle */ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 08f6c7fbbcd5a43ae123dae6853dd80b1e730984..bea0c4aa34ad9bc5417c29a6bd061b0d0a693349 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1263,7 +1263,11 @@ static ivas_error initIsmMasaRendering( ivas_td_binaural_close( &inputIsm->tdRendWrapper.hBinRendererTd ); } +#ifndef FIX_1288_SPLIT_REND_XSAN ivas_rend_closeCrend( &inputIsm->crendWrapper, inputIsm->base.ctx.pSplitRendWrapper != NULL ? inputIsm->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses : 1 ); +#else + ivas_rend_closeCrend( &inputIsm->crendWrapper ); +#endif ivas_reverb_close( &inputIsm->hReverb ); @@ -1390,7 +1394,11 @@ static void clearInputIsm( initRendInputBase( &inputIsm->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); /* Free input's internal handles */ +#ifndef FIX_1288_SPLIT_REND_XSAN ivas_rend_closeCrend( &inputIsm->crendWrapper, inputIsm->base.ctx.pSplitRendWrapper != NULL ? inputIsm->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses : 1 ); +#else + ivas_rend_closeCrend( &inputIsm->crendWrapper ); +#endif ivas_reverb_close( &inputIsm->hReverb ); @@ -2088,7 +2096,11 @@ static ivas_error initMcBinauralRendering( /* if we need to use TD renderer and CREND was open, close it */ if ( useTDRend ) { +#ifndef FIX_1288_SPLIT_REND_XSAN ivas_rend_closeCrend( &inputMc->crendWrapper, inputMc->base.ctx.pSplitRendWrapper != NULL ? inputMc->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses : 1 ); +#else + ivas_rend_closeCrend( &inputMc->crendWrapper ); +#endif } if ( !reconfigureFlag || ( !useTDRend && outConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB && inputMc->hReverb != NULL ) ) @@ -2180,7 +2192,11 @@ static ivas_error initMcMasaRendering( ivas_td_binaural_close( &inputMc->tdRendWrapper.hBinRendererTd ); } +#ifndef FIX_1288_SPLIT_REND_XSAN ivas_rend_closeCrend( &inputMc->crendWrapper, inputMc->base.ctx.pSplitRendWrapper != NULL ? inputMc->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses : 1 ); +#else + ivas_rend_closeCrend( &inputMc->crendWrapper ); +#endif ivas_reverb_close( &inputMc->hReverb ); @@ -2365,7 +2381,11 @@ static void clearInputMc( efap_free_data( &inputMc->efapInWrapper.hEfap ); } +#ifndef FIX_1288_SPLIT_REND_XSAN ivas_rend_closeCrend( &inputMc->crendWrapper, inputMc->base.ctx.pSplitRendWrapper != NULL ? inputMc->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses : 1 ); +#else + ivas_rend_closeCrend( &inputMc->crendWrapper ); +#endif ivas_reverb_close( &inputMc->hReverb ); @@ -2582,7 +2602,11 @@ static ivas_error initSbaMasaRendering( { ivas_error error; +#ifndef FIX_1288_SPLIT_REND_XSAN ivas_rend_closeCrend( &inputSba->crendWrapper, inputSba->base.ctx.pSplitRendWrapper != NULL ? inputSba->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses : 1 ); +#else + ivas_rend_closeCrend( &inputSba->crendWrapper ); +#endif if ( ( error = ivas_dirac_ana_open( &inputSba->hDirAC, inSampleRate ) ) != IVAS_ERR_OK ) { @@ -2660,7 +2684,11 @@ static void clearInputSba( initRendInputBase( &inputSba->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); /* Free input's internal handles */ +#ifndef FIX_1288_SPLIT_REND_XSAN ivas_rend_closeCrend( &inputSba->crendWrapper, rendCtx.pSplitRendWrapper != NULL ? rendCtx.pSplitRendWrapper->multiBinPoseData.num_poses : 1 ); +#else + ivas_rend_closeCrend( &inputSba->crendWrapper ); +#endif if ( inputSba->cldfbRendWrapper.hCldfbRend != NULL ) { diff --git a/scripts/lc3plus_lib_setup/get_lc3plus.sh b/scripts/lc3plus_lib_setup/get_lc3plus.sh index ea2a893d1993fc2750a128ffdeb7b71f21033244..d44aff06996dd9c812d29804c36602f9c3c18c38 100755 --- a/scripts/lc3plus_lib_setup/get_lc3plus.sh +++ b/scripts/lc3plus_lib_setup/get_lc3plus.sh @@ -57,6 +57,10 @@ find lib_lc3plus -name '*.[ch]' -type f -print0 | \ xargs -0 -I {} \ sed -i 's/^#[[:space:]]\+/#/' {} +# fix for sanitizer issues +sed -i 's/st->low << 8/(LC3_INT)((LC3_UINT32)st->low << 8)/' lib_lc3plus/ari_codec.c +sed -i 's/~3/(uintptr_t)(~3)/' lib_lc3plus/lc3.c + # Add .clang-format file to lib_lc3plus to disable formatting there printf "Disabling clang-format in lib_lc3plus directory\n" printf ' diff --git a/tests/renderer/utils.py b/tests/renderer/utils.py index 9176feaa1f9d988f81ae7959102471044a5e456b..1e66afd606b98804429e02538d97f2843593f4fd 100644 --- a/tests/renderer/utils.py +++ b/tests/renderer/utils.py @@ -67,53 +67,54 @@ from ..cmp_pcm import cmp_pcm from ..conftest import parse_properties, get_split_idx -def run_cmd(cmd, test_info, env=None): - logging.info(f"\nRunning command\n{' '.join(cmd)}\n") +def _run_cmd(cmd, env, test_info=None): + """ + Helper function for running some command. + Raises a SystemError if either the return code is non-zero or a USAN printout is detected + """ + proc = sp.run(cmd, capture_output=True, text=True, env=env) + stdout = proc.stdout + proc.stderr + + # check for USAN error first + if "UndefinedBehaviorSanitizer" in stdout: + error = f"USAN error detected in stdout of command: {' '.join(cmd)}\n{stdout}" + if test_info is not None: + test_info.error = error + raise SystemError(error) + + # then handle possible crash try: - sp.run(cmd, check=True, capture_output=True, text=True, env=env) + proc.check_returncode() except sp.CalledProcessError as e: - test_info.error = f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}" - raise SystemError(test_info.error) + error = f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}" + if test_info is not None: + test_info.error = error + raise SystemError(error) + + +def run_cmd(cmd, test_info, env=None): + logging.info(f"\nRunning command\n{' '.join(cmd)}\n") + _run_cmd(cmd, env, test_info) def run_isar_ext_rend_cmd(cmd, env=None): logging.info(f"\nRunning ISAR EXT REND command\n{' '.join(cmd)}\n") - try: - sp.run(cmd, check=True, capture_output=True, text=True, env=env) - except sp.CalledProcessError as e: - raise SystemError( - f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}" - ) + _run_cmd(cmd, env) def run_ivas_isar_enc_cmd(cmd, env=None): logging.info(f"\nRunning IVAS ISAR encoder command\n{' '.join(cmd)}\n") - try: - sp.run(cmd, check=True, capture_output=True, text=True, env=env) - except sp.CalledProcessError as e: - raise SystemError( - f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}" - ) + _run_cmd(cmd, env) def run_ivas_isar_dec_cmd(cmd, env=None): logging.info(f"\nDUT decoder command:\n\t{' '.join(cmd)}\n") - try: - sp.run(cmd, check=True, capture_output=True, text=True, env=env) - except sp.CalledProcessError as e: - raise SystemError( - f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}" - ) + _run_cmd(cmd, env) def run_isar_post_rend_cmd(cmd, env=None): logging.info(f"\nRunning ISAR post renderer command\n{' '.join(cmd)}\n") - try: - sp.run(cmd, check=True, capture_output=True, text=True, env=env) - except sp.CalledProcessError as e: - raise SystemError( - f"Command returned non-zero exit status ({e.returncode}): {' '.join(e.cmd)}\n{e.stderr}\n{e.stdout}" - ) + _run_cmd(cmd, env) def check_BE( @@ -251,7 +252,7 @@ def run_renderer( for k, v in FORMAT_TO_METADATA_FILES_LTV.items(): format_to_file[k] = str(v).replace( str(LTV_DIR), str(test_info.config.option.ltv_dir) - ) + ) else: format_to_file = FORMAT_TO_FILE_LTV format_to_metadata_files = FORMAT_TO_METADATA_FILES_LTV