summaryrefslogtreecommitdiff
path: root/ext/mysqli
diff options
context:
space:
mode:
authorAndrey Hristov <andrey@php.net>2005-11-30 16:20:25 +0000
committerAndrey Hristov <andrey@php.net>2005-11-30 16:20:25 +0000
commit4ec16344a9d6c4fb56eb0cbb89a604e1b7572a52 (patch)
tree02d52e890ec89cbe70ddf4c3cc53f5a32ea026e4 /ext/mysqli
parenta8c0463961d148f2890e06d61647d25493c88945 (diff)
downloadphp-git-4ec16344a9d6c4fb56eb0cbb89a604e1b7572a52.tar.gz
add a test case
fix incorrect handling of unsigned bigint. optimize handling of unsigned int
Diffstat (limited to 'ext/mysqli')
-rw-r--r--ext/mysqli/mysqli_api.c45
-rw-r--r--ext/mysqli/tests/bug35103.phpt68
2 files changed, 96 insertions, 17 deletions
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index 7e4ef4d027..3a8b26fd66 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -617,8 +617,7 @@ PHP_FUNCTION(mysqli_stmt_fetch)
zval *mysql_stmt;
unsigned int i;
ulong ret;
- int lval;
- unsigned int ulval;
+ unsigned int uval;
double dval;
my_ulonglong llval;
@@ -653,19 +652,24 @@ PHP_FUNCTION(mysqli_stmt_fetch)
&& (stmt->stmt->fields[i].flags & UNSIGNED_FLAG))
{
/* unsigned int (11) */
- char tmp[12];
- memcpy (&ulval, stmt->result.buf[i].val, sizeof(lval));
- if (ulval > INT_MAX) {
- sprintf((char *)&tmp, "%u", ulval);
- ZVAL_STRING(stmt->result.vars[i], tmp, 1);
- } else {
- memcpy(&lval, stmt->result.buf[i].val, sizeof(lval));
- ZVAL_LONG(stmt->result.vars[i], lval);
+ uval= *(unsigned int *) stmt->result.buf[i].val;
+
+ if (uval > INT_MAX) {
+ char *tmp, *p;
+ int j=10;
+ tmp= emalloc(11);
+ p= &tmp[9];
+ do {
+ *p-- = (uval % 10) + 48;
+ uval = uval / 10;
+ } while (--j > 0);
+ tmp[10]= '\0';
+ /* unsigned int > INT_MAX is 10 digis - ALWAYS */
+ ZVAL_STRINGL(stmt->result.vars[i], tmp, 10, 0);
+ break;
}
- } else {
- memcpy(&lval, stmt->result.buf[i].val, sizeof(lval));
- ZVAL_LONG(stmt->result.vars[i], lval);
}
+ ZVAL_LONG(stmt->result.vars[i], *(int *)stmt->result.buf[i].val);
break;
case IS_DOUBLE:
memcpy(&dval, stmt->result.buf[i].val, sizeof(dval));
@@ -673,14 +677,21 @@ PHP_FUNCTION(mysqli_stmt_fetch)
break;
case IS_STRING:
if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG) {
- char tmp[50];
- memcpy (&llval, stmt->result.buf[i].val, sizeof(my_ulonglong));
- if (llval != (long)llval) {
+ my_bool uns= (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0;
+ llval= *(my_ulonglong *) stmt->result.buf[i].val;
+#if SIZEOF_LONG==8
+ if (uns && llval > 9223372036854775807L) {
+#elif SIZEOF_LONG==4
+ if ((uns && llval > 2147483647LL) ||
+ (!uns && (( 2147483647LL < (long long) llval) || (-2147483648LL > (long long) llval))))
+ {
+#endif
+ char tmp[22];
/* even though lval is declared as unsigned, the value
* may be negative. Therefor we cannot use %llu and must
* use %lld.
*/
- sprintf((char *)&tmp, "%lld", llval);
+ sprintf((char *)&tmp, (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? "%llu":"%lld", llval);
ZVAL_STRING(stmt->result.vars[i], tmp, 1);
} else {
ZVAL_LONG(stmt->result.vars[i], llval);
diff --git a/ext/mysqli/tests/bug35103.phpt b/ext/mysqli/tests/bug35103.phpt
new file mode 100644
index 0000000000..b6118b9b2b
--- /dev/null
+++ b/ext/mysqli/tests/bug35103.phpt
@@ -0,0 +1,68 @@
+--TEST--
+bug #35103 Bad handling of unsigned bigint
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+
+$drop = <<<EOSQL
+DROP TABLE test_bint;
+DROP TABLE test_buint;
+EOSQL;
+ include "connect.inc";
+
+ $mysql = new mysqli($host, $user, $passwd, "test");
+ $mysql->query("DROP TABLE IF EXISTS test_bint");
+ $mysql->query("CREATE TABLE test_bint (a bigint(20) default NULL) ENGINE=MYISAM");
+ $mysql->query("INSERT INTO test_bint VALUES (9223372036854775807),(-9223372036854775808),(-2147483648),(-2147483649),(-2147483647),(2147483647),(2147483648),(2147483649)");
+
+ $mysql->query("DROP TABLE IF EXISTS test_buint");
+ $mysql->query("CREATE TABLE test_buint (a bigint(20) unsigned default NULL)");
+ $mysql->query("INSERT INTO test_buint VALUES (18446744073709551615),(9223372036854775807),(9223372036854775808),(2147483647),(2147483649),(4294967295)");
+
+ $stmt = $mysql->prepare("SELECT a FROM test_bint ORDER BY a");
+ $stmt->bind_result($v);
+ $stmt->execute();
+ $i=0;
+ echo "BIG INT SIGNED, TEST\n";
+ while ($i++ < 8) {
+ $stmt->fetch();
+ echo $v, "\n";
+ }
+ $stmt->close();
+
+ echo str_repeat("-", 20), "\n";
+
+ $stmt = $mysql->prepare("SELECT a FROM test_buint ORDER BY a");
+ $stmt->bind_result($v2);
+ $stmt->execute();
+ $j=0;
+ echo "BIG INT UNSIGNED TEST\n";
+ while ($j++ < 6) {
+ $stmt->fetch();
+ echo $v2, "\n";
+ }
+ $stmt->close();
+
+ $mysql->multi_query($drop);
+
+ $mysql->close();
+?>
+--EXPECT--
+BIG INT SIGNED, TEST
+-9223372036854775808
+-2147483649
+-2147483648
+-2147483647
+2147483647
+2147483648
+2147483649
+9223372036854775807
+--------------------
+BIG INT UNSIGNED TEST
+2147483647
+2147483649
+4294967295
+9223372036854775807
+9223372036854775808
+18446744073709551615