CVE-2016-6871 (published 2017-02-17T17:59Z)

Integer overflow in bcmath in Facebook HHVM before 3.15.0 allows attackers to have unspecified impact via unknown vectors, which triggers a buffer overflow.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-190
cwe_name: Integer Overflow or Wraparound
description: The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
extended_description: 
            
            
            
            
         
         

Fix information:
repo_url: https://github.com/facebook/hhvm
commit_details: repo_url: https://github.com/facebook/hhvm
author: mwilliams@fb.com
author_date: 2016-08-01 15:13:10-07:00
msg: Fix buffer overrun due to integer overflow in bcmath

Summary: scale gets passed around as an int inside the library.

Reviewed By: mxw

Differential Revision: D3624520

fbshipit-source-id: d39927413cec24fda2e475a296ad5d9019ccef0a
repository: repo_url: https://github.com/facebook/hhvm
repo_name: facebook/hhvm
description: A virtual machine for executing programs written in Hack.
repo_language: Hack
owner: facebook
file_changes: filename: ext_bcmath.cpp
change_type: ModificationType.MODIFY
diff: @@ -39,6 +39,15 @@ static IMPLEMENT_THREAD_LOCAL(bcmath_data, s_globals);
 
 ///////////////////////////////////////////////////////////////////////////////
 
+static int64_t adjust_scale(int64_t scale) {
+  if (scale < 0) {
+    scale = BCG(bc_precision);
+    if (scale < 0) scale = 0;
+  }
+  if ((uint64_t)scale > StringData::MaxSize) return StringData::MaxSize;
+  return scale;
+}
+
 static void php_str2num(bc_num *num, const char *str) {
   const char *p;
   if (!(p = strchr(str, '.'))) {
@@ -55,7 +64,7 @@ static bool HHVM_FUNCTION(bcscale, int64_t scale) {
 
 static String HHVM_FUNCTION(bcadd, const String& left, const String& right,
                             int64_t scale /* = -1 */) {
-  if (scale < 0) scale = BCG(bc_precision);
+  scale = adjust_scale(scale);
   bc_num first, second, result;
   bc_init_num(&first);
   bc_init_num(&second);
@@ -75,7 +84,7 @@ static String HHVM_FUNCTION(bcadd, const String& left, const String& right,
 
 static String HHVM_FUNCTION(bcsub, const String& left, const String& right,
                             int64_t scale /* = -1 */) {
-  if (scale < 0) scale = BCG(bc_precision);
+  scale = adjust_scale(scale);
   bc_num first, second, result;
   bc_init_num(&first);
   bc_init_num(&second);
@@ -95,7 +104,7 @@ static String HHVM_FUNCTION(bcsub, const String& left, const String& right,
 
 static int64_t HHVM_FUNCTION(bccomp, const String& left, const String& right,
                              int64_t scale /* = -1 */) {
-  if (scale < 0) scale = BCG(bc_precision);
+  scale = adjust_scale(scale);
   bc_num first, second;
   bc_init_num(&first);
   bc_init_num(&second);
@@ -109,7 +118,7 @@ static int64_t HHVM_FUNCTION(bccomp, const String& left, const String& right,
 
 static String HHVM_FUNCTION(bcmul, const String& left, const String& right,
                             int64_t scale /* = -1 */) {
-  if (scale < 0) scale = BCG(bc_precision);
+  scale = adjust_scale(scale);
   bc_num first, second, result;
   bc_init_num(&first);
   bc_init_num(&second);
@@ -129,7 +138,7 @@ static String HHVM_FUNCTION(bcmul, const String& left, const String& right,
 
 static Variant HHVM_FUNCTION(bcdiv, const String& left, const String& right,
                int64_t scale /* = -1 */) {
-  if (scale < 0) scale = BCG(bc_precision);
+  scale = adjust_scale(scale);
   bc_num first, second, result;
   bc_init_num(&first);
   bc_init_num(&second);
@@ -171,7 +180,7 @@ static Variant HHVM_FUNCTION(bcmod, const String& left, const String& right) {
 
 static String HHVM_FUNCTION(bcpow, const String& left, const String& right,
                            int64_t scale /* = -1 */) {
-  if (scale < 0) scale = BCG(bc_precision);
+  scale = adjust_scale(scale);
   bc_num first, second, result;
   bc_init_num(&first);
   bc_init_num(&second);
@@ -193,7 +202,7 @@ static String HHVM_FUNCTION(bcpow, const String& left, const String& right,
 
 static Variant HHVM_FUNCTION(bcpowmod, const String& left, const String& right,
                              const String& modulus, int64_t scale /* = -1 */) {
-  if (scale < 0) scale = BCG(bc_precision);
+  scale = adjust_scale(scale);
   bc_num first, second, mod, result;
   bc_init_num(&first);
   bc_init_num(&second);
@@ -220,7 +229,7 @@ static Variant HHVM_FUNCTION(bcpowmod, const String& left, const String& right,
 
 static Variant HHVM_FUNCTION(bcsqrt, const String& operand,
                              int64_t scale /* = -1 */) {
-  if (scale < 0) scale = BCG(bc_precision);
+  scale = adjust_scale(scale);
   bc_num result;
   bc_init_num(&result);
   SCOPE_EXIT {

programming_language: C++
filename: bccomp_overflow.php
change_type: ModificationType.ADD
diff: @@ -0,0 +1,7 @@
+<?php
+
+$intMaxPre = PHP_INT_MAX - 1;
+$stringNormal = 'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+$number_bccomp_10 = bccomp("2015.5", $stringNormal, $intMaxPre);
+var_dump($number_bccomp_10);

programming_language: PHP
filename: bccomp_overflow.php.expect
change_type: ModificationType.ADD
diff: @@ -0,0 +1 @@
+int(1)

programming_language: SQL