diff --git a/Workspace_msvc/lib_com.vcxproj b/Workspace_msvc/lib_com.vcxproj
index c28b36a1454bdb9bd3245a0ce9050d258602a13a..e1a44fceaaf90a4ac963c82b089e194f0649cf25 100644
--- a/Workspace_msvc/lib_com.vcxproj
+++ b/Workspace_msvc/lib_com.vcxproj
@@ -209,6 +209,7 @@
+
@@ -311,4 +312,4 @@
-
\ No newline at end of file
+
diff --git a/Workspace_msvc/lib_com.vcxproj.filters b/Workspace_msvc/lib_com.vcxproj.filters
index 5534c8a0191afe5419f543c6ef6f08703e531fc8..8eb71a10687b62c11a595710de6db0d56acabbc2 100644
--- a/Workspace_msvc/lib_com.vcxproj.filters
+++ b/Workspace_msvc/lib_com.vcxproj.filters
@@ -385,6 +385,9 @@
common_ivas_c
+
+ common_ivas_c
+
common_ivas_c
@@ -557,4 +560,4 @@
{b95b7bed-a666-4a00-9332-2b528638503e}
-
\ No newline at end of file
+
diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h
index 2a226b367e4378839207e73462dea66c9c167cab..2ae737251b47bca5c205c04fea9b02792ef43ef1 100644
--- a/lib_com/ivas_error.h
+++ b/lib_com/ivas_error.h
@@ -93,6 +93,9 @@ typedef enum
IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED,
IVAS_ERR_TSM_NOT_ENABLED,
IVAS_ERR_FETCH_SIZE_NO_MULTIPLE_OF_5MS,
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ IVAS_ERR_INVALID_QUATERNION,
+#endif
#ifdef DEBUGGING
IVAS_ERR_INVALID_FORCE_MODE,
#ifdef DEBUG_AGC_ENCODER_CMD_OPTION
@@ -282,6 +285,10 @@ static inline const char *ivas_error_to_string( ivas_error error_code )
return "Invalid index";
case IVAS_ERR_EXTERNAL_ORIENTATION_INVALID_FORMAT:
return "Euler angles were detected in the input but only Quaternions are supported";
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ case IVAS_ERR_INVALID_QUATERNION:
+ return "Non-unit quaternion or Euler angles out of valid range";
+#endif
default:
break;
}
diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h
index 31601d7f30d08a336c05b11be41de8054b7372f0..fa7942d727df278e2ee39e94e1762bd018f72cf7 100755
--- a/lib_com/ivas_prot.h
+++ b/lib_com/ivas_prot.h
@@ -827,6 +827,11 @@ void QuaternionInverse(
);
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ivas_error validate_quaternion( IVAS_QUATERNION q );
+#endif
+
+
/*----------------------------------------------------------------------------------*
* Internal rendering prototypes
*----------------------------------------------------------------------------------*/
diff --git a/lib_com/ivas_quaternion.c b/lib_com/ivas_quaternion.c
new file mode 100644
index 0000000000000000000000000000000000000000..59971b04e7d3b19b5464b06a0173dd9ba0827b8b
--- /dev/null
+++ b/lib_com/ivas_quaternion.c
@@ -0,0 +1,69 @@
+/******************************************************************************************************
+
+ (C) 2022-2026 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository. All Rights Reserved.
+
+ This software is protected by copyright law and by international treaties.
+ The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
+ Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
+ Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
+ Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
+ contributors to this repository retain full ownership rights in their respective contributions in
+ the software. This notice grants no license of any kind, including but not limited to patent
+ license, nor is any license granted by implication, estoppel or otherwise.
+
+ Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
+ contributions.
+
+ This software is provided "AS IS", without any express or implied warranties. The software is in the
+ development stage. It is intended exclusively for experts who have experience with such software and
+ solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
+ and fitness for a particular purpose are hereby disclaimed and excluded.
+
+ Any dispute, controversy or claim arising under or in relation to providing this software shall be
+ submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
+ accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
+ the United Nations Convention on Contracts on the International Sales of Goods.
+
+*******************************************************************************************************/
+
+#include "options.h"
+#include "ivas_prot.h"
+#include
+
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+/*---------------------------------------------------------------------*
+ * validate_quaternion( )
+ *
+ * Ensures given quaternion has close to unit norm.
+ * If Euler angles (w == -3), checks if angles are within reasonable ranges.
+ *---------------------------------------------------------------------*/
+ivas_error validate_quaternion( IVAS_QUATERNION q )
+{
+ float norm_squared;
+ float epsilon;
+
+ epsilon = 1e-5f;
+
+ // Euler angles if w == -3
+ if ( q.w == -3.0f &&
+ ( q.x < -180.0f || 180.0f < q.x // yaw out of range
+ || q.y < -90.0f || 90.0f < q.y // pitch out of range
+ || q.z < -180.0f || 180.0f < q.z // roll out of range
+ ) )
+ {
+ return IVAS_ERR_INVALID_QUATERNION;
+ }
+
+ norm_squared = q.w * q.w + q.x * q.x + q.y * q.y + q.z * q.z;
+ if ( fabsf( norm_squared - 1.0f ) < epsilon )
+ {
+ return IVAS_ERR_INVALID_QUATERNION;
+ }
+
+ return IVAS_ERR_OK;
+}
+#endif
diff --git a/lib_com/options.h b/lib_com/options.h
index 123c0590c61fafc9e725d2f9bf9e294104003f1c..f6c5c0079ff65cc1aed93d66e147bb96a2254362 100644
--- a/lib_com/options.h
+++ b/lib_com/options.h
@@ -165,6 +165,7 @@
#define FIX_FLOAT_1526_DIRAC_MEM_LEAK /* FhG: potential memory leak in DirAC handles in case of format switching */
#define ALIGN_ACELP_CORE /* VA: align ACELP core functions with BASOP */
#define FIX_1532_MSAN_ERR_AMR_FIRST_FRAME_IS_SID /* FhG: fix msan complaint in AMR-WB when first frame is an SID */
+#define FIX_FLOAT_1529_VALIDATE_QUATERNIONS /* FhG: validate quaternion inputs at API boundary */
/* #################### End BE switches ################################## */
diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c
index 0afec7310f1d418fba7b53751caff22a671d131a..0bf54d67dc71cdf75afde10f5e0489a961391df4 100644
--- a/lib_dec/lib_dec.c
+++ b/lib_dec/lib_dec.c
@@ -2582,6 +2582,13 @@ ivas_error IVAS_DEC_FeedHeadTrackData(
return IVAS_ERR_UNEXPECTED_NULL_POINTER;
}
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ if ( ( error = validate_quaternion( orientation ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+#endif
+
hHeadTrackData = hIvasDec->st_ivas->hHeadTrackData;
if ( hHeadTrackData == NULL )
@@ -2624,12 +2631,22 @@ ivas_error IVAS_DEC_FeedRefRotData(
)
{
ivas_orient_trk_state_t *pOtr;
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ ivas_error error;
+#endif
if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hHeadTrackData == NULL || hIvasDec->st_ivas->hHeadTrackData->OrientationTracker == NULL )
{
return IVAS_ERR_UNEXPECTED_NULL_POINTER;
}
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ if ( ( error = validate_quaternion( rotation ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+#endif
+
pOtr = hIvasDec->st_ivas->hHeadTrackData->OrientationTracker;
pOtr->refRot.w = rotation.w;
@@ -2689,12 +2706,22 @@ ivas_error IVAS_DEC_FeedExternalOrientationData(
)
{
EXTERNAL_ORIENTATION_HANDLE hExternalOrientationData;
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ ivas_error error;
+#endif
if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL )
{
return IVAS_ERR_UNEXPECTED_NULL_POINTER;
}
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ if ( ( error = validate_quaternion( orientation ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+#endif
+
hExternalOrientationData = hIvasDec->st_ivas->hExtOrientationData;
if ( hExternalOrientationData == NULL )
diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c
index 3d9609359b4f4421c7275f10c57f97f886e463fe..1c0b5013d94b408abbca08c4f53472e3d414ad57 100644
--- a/lib_rend/lib_rend.c
+++ b/lib_rend/lib_rend.c
@@ -4931,6 +4931,12 @@ ivas_error IVAS_REND_SetHeadRotation(
{
return IVAS_ERR_UNEXPECTED_NULL_POINTER;
}
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ if ( ( error = validate_quaternion( headRot ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+#endif
if ( getAudioConfigType( hIvasRend->outputConfig ) != IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL )
{
@@ -5065,6 +5071,12 @@ ivas_error IVAS_REND_SetReferenceRotation(
{
return IVAS_ERR_UNEXPECTED_NULL_POINTER;
}
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ if ( ( error = validate_quaternion( refRot ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+#endif
if ( ( error = ivas_orient_trk_SetReferenceRotation( hIvasRend->headRotData.hOrientationTracker, refRot ) ) != IVAS_ERR_OK )
{
@@ -5167,6 +5179,10 @@ ivas_error IVAS_REND_SetExternalOrientation(
const int16_t sf_idx /* i : subframe index */
)
{
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ ivas_error error;
+#endif
+
/* Validate function arguments */
if ( hIvasRend == NULL || hIvasRend->hExternalOrientationData == NULL )
{
@@ -5179,6 +5195,13 @@ ivas_error IVAS_REND_SetExternalOrientation(
}
else
{
+#ifdef FIX_FLOAT_1529_VALIDATE_QUATERNIONS
+ if ( ( error = validate_quaternion( *orientation ) ) != IVAS_ERR_OK )
+ {
+ return error;
+ }
+
+#endif
QuaternionInverse( *orientation, &hIvasRend->hExternalOrientationData->Quaternions[sf_idx] );
hIvasRend->hExternalOrientationData->enableHeadRotation[sf_idx] = enableHeadRotation;