diff options
author | Andrey Hristov <andrey@php.net> | 2005-11-30 16:20:25 +0000 |
---|---|---|
committer | Andrey Hristov <andrey@php.net> | 2005-11-30 16:20:25 +0000 |
commit | 4ec16344a9d6c4fb56eb0cbb89a604e1b7572a52 (patch) | |
tree | 02d52e890ec89cbe70ddf4c3cc53f5a32ea026e4 /ext/mysqli | |
parent | a8c0463961d148f2890e06d61647d25493c88945 (diff) | |
download | php-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.c | 45 | ||||
-rw-r--r-- | ext/mysqli/tests/bug35103.phpt | 68 |
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 |