diff --git a/celt/arch.h b/celt/arch.h index dcfba763..6693408f 100644 --- a/celt/arch.h +++ b/celt/arch.h @@ -137,6 +137,22 @@ typedef float celt_sig; typedef float celt_norm; typedef float celt_ener; +#ifdef FLOAT_APPROX +/* This code should reliably detect NaN/inf even when -ffast-math is used. + Assumes IEEE 754 format. */ +static inline int celt_isnan(float x) +{ + union {float f; opus_uint32 i;} in; + in.f = x; + return ((in.i>>23)&0xFF)==0xFF && (in.i&0x007FFFFF)!=0; +} +#else +#ifdef __FAST_MATH__ +#error Cannot build libopus with -ffast-math unless FLOAT_APPROX is defined. This could result in crashes on extreme (e.g. NaN) input +#endif +#define celt_isnan(x) ((x)!=(x)) +#endif + #define Q15ONE 1.0f #define NORM_SCALING 1.f diff --git a/src/mlp.c b/src/mlp.c index 46386026..524e7711 100644 --- a/src/mlp.c +++ b/src/mlp.c @@ -75,6 +75,11 @@ static OPUS_INLINE float tansig_approx(float x) return 1; if (!(x>-8)) return -1; +#ifndef FIXED_POINT + /* Another check in case of -ffast-math */ + if (celt_isnan(x)) + return 0; +#endif if (x<0) { x=-x; diff --git a/src/mlp_data.c b/src/mlp_data.c index 401c4c02..c2fda4e2 100644 --- a/src/mlp_data.c +++ b/src/mlp_data.c @@ -1,6 +1,10 @@ /* The contents of this file was automatically generated by mlp_train.c It contains multi-layer perceptron (MLP) weights. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "mlp.h" /* RMS error was 0.138320, seed was 1361535663 */ diff --git a/src/opus_encoder.c b/src/opus_encoder.c index c819bb15..411e3d24 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -1452,7 +1452,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_ sum = celt_inner_prod(&pcm_buf[total_buffer*st->channels], &pcm_buf[total_buffer*st->channels], frame_size*st->channels); /* This should filter out both NaNs and ridiculous signals that could cause NaNs further down. */ - if (!(sum < 1e9)) + if (!(sum < 1e9) || celt_isnan(sum)) OPUS_CLEAR(&pcm_buf[total_buffer*st->channels], frame_size*st->channels); } #endif