[vlc-devel] [PATCH 1/4] src: replace MD5 implementation with BearSSLs one

Marvin Scholz epirat07 at gmail.com
Thu Jul 23 14:51:56 CEST 2020


---
 include/vlc_hash.h |  11 +-
 src/misc/md5.c     | 479 ++++++++++++++++++---------------------------
 2 files changed, 194 insertions(+), 296 deletions(-)

diff --git a/include/vlc_hash.h b/include/vlc_hash.h
index 0a853d5ad3..fae6125735 100644
--- a/include/vlc_hash.h
+++ b/include/vlc_hash.h
@@ -83,11 +83,10 @@
  */
 typedef struct vlc_hash_md5_ctx
 {
-    struct md5_s {
-        uint32_t A, B, C, D; /* chaining variables */
-        uint32_t nblocks;
-        uint8_t buf[64];
-        int count;
+    struct {
+        unsigned char buf[64];
+        uint64_t count;
+        uint32_t val[4];
     } priv; /**< \internal Private */
 } vlc_hash_md5_t;
 
@@ -136,7 +135,7 @@ VLC_API void vlc_hash_md5_Update(vlc_hash_md5_t *ctx, const void *data, size_t s
  * \param[out]    output Output buffer to write to
  * \param         size   Output buffer size
  */
-VLC_API void vlc_hash_md5_Finish(vlc_hash_md5_t *ctx, void *output, size_t size);
+VLC_API void vlc_hash_md5_Finish(const vlc_hash_md5_t *ctx, void *output, size_t size);
 
 /**
  * @}
diff --git a/src/misc/md5.c b/src/misc/md5.c
index 68657a4f0a..f5678ac6e9 100644
--- a/src/misc/md5.c
+++ b/src/misc/md5.c
@@ -1,30 +1,34 @@
-/*****************************************************************************
- * md5.c: not so strong MD5 hashing
- *****************************************************************************
- * Copyright (C) 1995,1996,1998,1999,2001,2002,
- *               2003  Free Software Foundation, Inc.
+/**
+ * MD5 hashing implementation
+ * \file md5.h
+ */
+
+/*
+ * Nearly all of this code was copied from BearSSL and adapted to
+ * VLCs usecase and API.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
+ * Copyright (c) 2016 Thomas Pornin <pornin at bolet.org>
  *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-/* md5.c - MD5 Message-Digest Algorithm
+ * Permission is hereby granted, free of charge, to any person obtaining 
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
  *
- * According to the definition of MD5 in RFC 1321 from April 1992.
- * NOTE: This is *not* the same file as the one from glibc.
- * Written by Ulrich Drepper <drepper at gnu.ai.mit.edu>, 1995.
- * heavily modified for GnuPG by Werner Koch <wk at gnupg.org>
+ * The above copyright notice and this permission notice shall be 
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
  */
 
 /* Test values:
@@ -45,309 +49,204 @@
 #include <vlc_common.h>
 #include <vlc_hash.h>
 
-typedef uint32_t u32;
-typedef uint8_t byte;
-#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+/* Begin common helpers */
 
-typedef struct md5_s MD5_CONTEXT;
+static inline uint32_t
+br_dec32le(const void *src)
+{
+    const unsigned char *buf;
 
+    buf = src;
+    return (uint32_t)buf[0]
+        | ((uint32_t)buf[1] << 8)
+        | ((uint32_t)buf[2] << 16)
+        | ((uint32_t)buf[3] << 24);
+}
 
 static void
-md5_init( void *context )
+br_range_dec32le(uint32_t *v, size_t num, const void *src)
 {
-  MD5_CONTEXT *ctx = context;
-
-  ctx->A = 0x67452301;
-  ctx->B = 0xefcdab89;
-  ctx->C = 0x98badcfe;
-  ctx->D = 0x10325476;
+    const unsigned char *buf;
 
-  ctx->nblocks = 0;
-  ctx->count = 0;
+    buf = src;
+    while (num -- > 0) {
+        *v ++ = br_dec32le(buf);
+        buf += 4;
+    }
 }
 
+static inline void
+br_enc32le(void *dst, uint32_t x)
+{
+    unsigned char *buf;
 
-/* These are the four functions used in the four steps of the MD5 algorithm
-   and defined in the RFC 1321.  The first function is a little bit optimized
-   (as found in Colin Plumbs public domain implementation).  */
-/* #define FF(b, c, d) ((b & c) | (~b & d)) */
-#define FF(b, c, d) (d ^ (b & (c ^ d)))
-#define FG(b, c, d) FF (d, b, c)
-#define FH(b, c, d) (b ^ c ^ d)
-#define FI(b, c, d) (c ^ (b | ~d))
-
+    buf = dst;
+    buf[0] = (unsigned char)x;
+    buf[1] = (unsigned char)(x >> 8);
+    buf[2] = (unsigned char)(x >> 16);
+    buf[3] = (unsigned char)(x >> 24);
+}
 
-/****************
- * transform n*64 bytes
- */
 static void
-transform ( MD5_CONTEXT *ctx, const unsigned char *data )
+br_range_enc32le(void *dst, const uint32_t *v, size_t num)
 {
-  u32 correct_words[16];
-  register u32 A = ctx->A;
-  register u32 B = ctx->B;
-  register u32 C = ctx->C;
-  register u32 D = ctx->D;
-  u32 *cwp = correct_words;
-
-#ifdef WORDS_BIGENDIAN
-  {
-    int i;
-    byte *p2, *p1;
-    for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 )
-      {
-        p2[3] = *p1++;
-	p2[2] = *p1++;
-	p2[1] = *p1++;
-	p2[0] = *p1++;
-      }
-  }
-#else
-  memcpy( correct_words, data, 64 );
-#endif
+    unsigned char *buf;
+
+    buf = dst;
+    while (num -- > 0) {
+        br_enc32le(buf, *v ++);
+        buf += 4;
+    }
+}
 
+static inline void
+br_enc64le(void *dst, uint64_t x)
+{
+    unsigned char *buf;
 
-#define OP(a, b, c, d, s, T) \
-  do			         	   \
-    {					   \
-      a += FF (b, c, d) + (*cwp++) + T;    \
-      a = rol(a, s);			   \
-      a += b;				   \
-    }					   \
-  while (0)
-
-  /* Before we start, one word about the strange constants.
-     They are defined in RFC 1321 as
-
-     T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
-  */
-
-  /* Round 1.  */
-  OP (A, B, C, D,  7, 0xd76aa478);
-  OP (D, A, B, C, 12, 0xe8c7b756);
-  OP (C, D, A, B, 17, 0x242070db);
-  OP (B, C, D, A, 22, 0xc1bdceee);
-  OP (A, B, C, D,  7, 0xf57c0faf);
-  OP (D, A, B, C, 12, 0x4787c62a);
-  OP (C, D, A, B, 17, 0xa8304613);
-  OP (B, C, D, A, 22, 0xfd469501);
-  OP (A, B, C, D,  7, 0x698098d8);
-  OP (D, A, B, C, 12, 0x8b44f7af);
-  OP (C, D, A, B, 17, 0xffff5bb1);
-  OP (B, C, D, A, 22, 0x895cd7be);
-  OP (A, B, C, D,  7, 0x6b901122);
-  OP (D, A, B, C, 12, 0xfd987193);
-  OP (C, D, A, B, 17, 0xa679438e);
-  OP (B, C, D, A, 22, 0x49b40821);
-
-#undef OP
-#define OP(f, a, b, c, d, k, s, T)  \
-    do								      \
-      { 							      \
-	a += f (b, c, d) + correct_words[k] + T;		      \
-	a = rol(a, s);						      \
-	a += b; 						      \
-      } 							      \
-    while (0)
-
-  /* Round 2.  */
-  OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
-  OP (FG, D, A, B, C,  6,  9, 0xc040b340);
-  OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
-  OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
-  OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
-  OP (FG, D, A, B, C, 10,  9, 0x02441453);
-  OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
-  OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
-  OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
-  OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
-  OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
-  OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
-  OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
-  OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
-  OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
-  OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
-
-  /* Round 3.  */
-  OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
-  OP (FH, D, A, B, C,  8, 11, 0x8771f681);
-  OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
-  OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
-  OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
-  OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
-  OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
-  OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
-  OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
-  OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
-  OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
-  OP (FH, B, C, D, A,  6, 23, 0x04881d05);
-  OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
-  OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
-  OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
-  OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
-
-  /* Round 4.  */
-  OP (FI, A, B, C, D,  0,  6, 0xf4292244);
-  OP (FI, D, A, B, C,  7, 10, 0x432aff97);
-  OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
-  OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
-  OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
-  OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
-  OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
-  OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
-  OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
-  OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
-  OP (FI, C, D, A, B,  6, 15, 0xa3014314);
-  OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
-  OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
-  OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
-  OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
-  OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
-
-  /* Put checksum in context given as argument.  */
-  ctx->A += A;
-  ctx->B += B;
-  ctx->C += C;
-  ctx->D += D;
+    buf = dst;
+    br_enc32le(buf, (uint32_t)x);
+    br_enc32le(buf + 4, (uint32_t)(x >> 32));
 }
 
+/* End common helpers */
 
+#define F(B, C, D)     ((((C) ^ (D)) & (B)) ^ (D))
+#define G(B, C, D)     ((((C) ^ (B)) & (D)) ^ (C))
+#define H(B, C, D)     ((B) ^ (C) ^ (D))
+#define I(B, C, D)     ((C) ^ ((B) | ~(D)))
 
-/* The routine updates the message-digest context to
- * account for the presence of each of the characters inBuf[0..inLen-1]
- * in the message whose digest is being computed.
- */
-static void
-md5_write( void *context, const void *inbuf_arg , size_t inlen)
-{
-  const unsigned char *inbuf = inbuf_arg;
-  MD5_CONTEXT *hd = context;
-
-  if( hd->count == 64 )  /* flush the buffer */
-    {
-      transform( hd, hd->buf );
-      hd->count = 0;
-      hd->nblocks++;
-    }
-  if( !inbuf )
-    return;
-
-  if( hd->count )
-    {
-      for( ; inlen && hd->count < 64; inlen-- )
-        hd->buf[hd->count++] = *inbuf++;
-      md5_write( hd, NULL, 0 );
-      if( !inlen )
-        return;
-    }
+#define ROTL(x, n)    (((x) << (n)) | ((x) >> (32 - (n))))
 
-  while( inlen >= 64 )
-    {
-      transform( hd, inbuf );
-      hd->count = 0;
-      hd->nblocks++;
-      inlen -= 64;
-      inbuf += 64;
-    }
-  for( ; inlen && hd->count < 64; inlen-- )
-    hd->buf[hd->count++] = *inbuf++;
+const uint32_t br_md5_IV[4] = {
+    0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476
+};
 
-}
+static const uint32_t K[64] = {
+    0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,
+    0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
+    0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
+    0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
 
+    0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
+    0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
+    0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
+    0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
 
+    0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,
+    0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
+    0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
+    0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
 
-/* The routine final terminates the message-digest computation and
- * ends with the desired message digest in mdContext->digest[0...15].
- * The handle is prepared for a new MD5 cycle.
- * Returns 16 bytes representing the digest.
- */
+    0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,
+    0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
+    0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,
+    0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
+};
+
+static const unsigned char MP[48] = {
+    1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
+    5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
+    0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9
+};
 
 static void
-md5_final( void *context)
+br_md5_round(const unsigned char *buf, uint32_t *val)
 {
-  MD5_CONTEXT *hd = context;
-  u32 t, msb, lsb;
-  byte *p;
-
-  md5_write(hd, NULL, 0); /* flush */;
-
-  t = hd->nblocks;
-  /* multiply by 64 to make a byte count */
-  lsb = t << 6;
-  msb = t >> 26;
-  /* add the count */
-  t = lsb;
-  if( (lsb += hd->count) < t )
-    msb++;
-  /* multiply by 8 to make a bit count */
-  t = lsb;
-  lsb <<= 3;
-  msb <<= 3;
-  msb |= t >> 29;
-
-  if( hd->count < 56 )  /* enough room */
-    {
-      hd->buf[hd->count++] = 0x80; /* pad */
-      while( hd->count < 56 )
-        hd->buf[hd->count++] = 0;  /* pad */
+    uint32_t m[16];
+    uint32_t a, b, c, d;
+    int i;
+
+    a = val[0];
+    b = val[1];
+    c = val[2];
+    d = val[3];
+
+    br_range_dec32le(m, 16, buf);
+
+    for (i = 0; i < 16; i += 4) {
+        a = b + ROTL(a + F(b, c, d) + m[i + 0] + K[i + 0],  7);
+        d = a + ROTL(d + F(a, b, c) + m[i + 1] + K[i + 1], 12);
+        c = d + ROTL(c + F(d, a, b) + m[i + 2] + K[i + 2], 17);
+        b = c + ROTL(b + F(c, d, a) + m[i + 3] + K[i + 3], 22);
     }
-  else  /* need one extra block */
-    {
-      hd->buf[hd->count++] = 0x80; /* pad character */
-      while( hd->count < 64 )
-        hd->buf[hd->count++] = 0;
-      md5_write(hd, NULL, 0);  /* flush */;
-      memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+    for (i = 16; i < 32; i += 4) {
+        a = b + ROTL(a + G(b, c, d) + m[MP[i - 16]] + K[i + 0],  5);
+        d = a + ROTL(d + G(a, b, c) + m[MP[i - 15]] + K[i + 1],  9);
+        c = d + ROTL(c + G(d, a, b) + m[MP[i - 14]] + K[i + 2], 14);
+        b = c + ROTL(b + G(c, d, a) + m[MP[i - 13]] + K[i + 3], 20);
+    }
+    for (i = 32; i < 48; i += 4) {
+        a = b + ROTL(a + H(b, c, d) + m[MP[i - 16]] + K[i + 0],  4);
+        d = a + ROTL(d + H(a, b, c) + m[MP[i - 15]] + K[i + 1], 11);
+        c = d + ROTL(c + H(d, a, b) + m[MP[i - 14]] + K[i + 2], 16);
+        b = c + ROTL(b + H(c, d, a) + m[MP[i - 13]] + K[i + 3], 23);
+    }
+    for (i = 48; i < 64; i += 4) {
+        a = b + ROTL(a + I(b, c, d) + m[MP[i - 16]] + K[i + 0],  6);
+        d = a + ROTL(d + I(a, b, c) + m[MP[i - 15]] + K[i + 1], 10);
+        c = d + ROTL(c + I(d, a, b) + m[MP[i - 14]] + K[i + 2], 15);
+        b = c + ROTL(b + I(c, d, a) + m[MP[i - 13]] + K[i + 3], 21);
     }
-  /* append the 64 bit count */
-  hd->buf[56] = lsb	   ;
-  hd->buf[57] = lsb >>  8;
-  hd->buf[58] = lsb >> 16;
-  hd->buf[59] = lsb >> 24;
-  hd->buf[60] = msb	   ;
-  hd->buf[61] = msb >>  8;
-  hd->buf[62] = msb >> 16;
-  hd->buf[63] = msb >> 24;
-  transform( hd, hd->buf );
-
-  p = hd->buf;
-#ifdef WORDS_BIGENDIAN
-#define X(a) do { *p++ = hd->a      ; *p++ = hd->a >> 8;      \
-	          *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
-#else /* little endian */
-#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0)
-#endif
-  X(A);
-  X(B);
-  X(C);
-  X(D);
-#undef X
-
-}
 
-#if 0
-static byte *
-md5_read( void *context )
-{
-  MD5_CONTEXT *hd = (MD5_CONTEXT *) context;
-  return hd->buf;
+    val[0] += a;
+    val[1] += b;
+    val[2] += c;
+    val[3] += d;
 }
-#endif
 
-/* Public API */
-void vlc_hash_md5_Init(vlc_hash_md5_t *ctx)
+void vlc_hash_md5_Init(vlc_hash_md5_t *c)
 {
-    md5_init(&ctx->priv);
+    memcpy(c->priv.val, br_md5_IV, sizeof c->priv.val);
+    c->priv.count = 0;
 }
 
-void vlc_hash_md5_Update(vlc_hash_md5_t *ctx, const void *data, size_t length)
+void vlc_hash_md5_Update(vlc_hash_md5_t *c, const void *data, size_t len)
 {
-    md5_write(&ctx->priv, data, length);
+    const unsigned char *buf;
+    size_t ptr;
+
+    buf = data;
+    ptr = (size_t)c->priv.count & 63;
+    while (len > 0) {
+        size_t clen;
+
+        clen = 64 - ptr;
+        if (clen > len) {
+            clen = len;
+        }
+        memcpy(c->priv.buf + ptr, buf, clen);
+        ptr += clen;
+        buf += clen;
+        len -= clen;
+        c->priv.count += (uint64_t)clen;
+        if (ptr == 64) {
+            br_md5_round(c->priv.buf, c->priv.val);
+            ptr = 0;
+        }
+    }
 }
 
-void vlc_hash_md5_Finish(vlc_hash_md5_t *ctx, void *output, size_t size)
+void vlc_hash_md5_Finish(const vlc_hash_md5_t *c, void *dst,  size_t len)
 {
-    assert(size >= VLC_HASH_MD5_DIGEST_SIZE);
-    md5_final(&ctx->priv);
-    memcpy(output, ctx->priv.buf, VLC_HASH_MD5_DIGEST_SIZE);
+    unsigned char buf[64];
+    uint32_t val[4];
+    size_t ptr;
+
+    assert(len >= VLC_HASH_MD5_DIGEST_SIZE);
+
+    ptr = (size_t)c->priv.count & 63;
+    memcpy(buf, c->priv.buf, ptr);
+    memcpy(val, c->priv.val, sizeof val);
+    buf[ptr ++] = 0x80;
+    if (ptr > 56) {
+        memset(buf + ptr, 0, 64 - ptr);
+        br_md5_round(buf, val);
+        memset(buf, 0, 56);
+    } else {
+        memset(buf + ptr, 0, 56 - ptr);
+    }
+    br_enc64le(buf + 56, c->priv.count << 3);
+    br_md5_round(buf, val);
+    br_range_enc32le(dst, val, 4);
 }
-- 
2.24.3 (Apple Git-128)



More information about the vlc-devel mailing list