From 697beca22dcdf04ee7720218741f34a7ec0bb86d Mon Sep 17 00:00:00 2001
From: Mark Harris <mark.hsj@gmail.com>
Date: Sun, 27 May 2018 17:47:28 -0700
Subject: [PATCH] Only call isqrt32() with a positive argument

Fixes test_opus_projection failure under ubsan, due to clz(0).
---
 celt/mathops.c                 |  3 ++-
 src/opus_multistream_encoder.c |  6 ++++--
 src/opus_projection_encoder.c  | 10 ++++++----
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/celt/mathops.c b/celt/mathops.c
index 78b52cc84..6ee9b9e10 100644
--- a/celt/mathops.c
+++ b/celt/mathops.c
@@ -38,7 +38,8 @@
 #include "mathops.h"
 
 /*Compute floor(sqrt(_val)) with exact arithmetic.
-  This has been tested on all possible 32-bit inputs.*/
+  _val must be greater than 0.
+  This has been tested on all possible 32-bit inputs greater than 0.*/
 unsigned isqrt32(opus_uint32 _val){
   unsigned b;
   unsigned g;
diff --git a/src/opus_multistream_encoder.c b/src/opus_multistream_encoder.c
index 1df9e7db8..aa48a61b0 100644
--- a/src/opus_multistream_encoder.c
+++ b/src/opus_multistream_encoder.c
@@ -108,12 +108,14 @@ static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled
    int acn_channels;
    int nondiegetic_channels;
 
+   if (nb_channels < 1 || nb_channels > 227)
+      return 0;
+
    order_plus_one = isqrt32(nb_channels);
    acn_channels = order_plus_one * order_plus_one;
    nondiegetic_channels = nb_channels - acn_channels;
 
-   if (order_plus_one < 1 || order_plus_one > 15 ||
-       (nondiegetic_channels != 0 && nondiegetic_channels != 2))
+   if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
       return 0;
 
    if (nb_streams)
diff --git a/src/opus_projection_encoder.c b/src/opus_projection_encoder.c
index 1c403c316..1fbcf471f 100644
--- a/src/opus_projection_encoder.c
+++ b/src/opus_projection_encoder.c
@@ -86,15 +86,17 @@ static int get_order_plus_one_from_channels(int channels, int *order_plus_one)
   /* Allowed numbers of channels:
    * (1 + n)^2 + 2j, for n = 0...14 and j = 0 or 1.
    */
+  if (channels < 1 || channels > 227)
+    return OPUS_BAD_ARG;
+
   order_plus_one_ = isqrt32(channels);
   acn_channels = order_plus_one_ * order_plus_one_;
   nondiegetic_channels = channels - acn_channels;
+  if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
+    return OPUS_BAD_ARG;
+
   if (order_plus_one)
     *order_plus_one = order_plus_one_;
-
-  if (order_plus_one_ < 1 || order_plus_one_ > 15 ||
-      (nondiegetic_channels != 0 && nondiegetic_channels != 2))
-    return OPUS_BAD_ARG;
   return OPUS_OK;
 }
 
-- 
GitLab