... with test (should fail before patch on all machines with
sizeof(int)<sizeof(int64_t), and pass after patch).
>From bb35171a11722a232832290cc6d66b7bff81aaa5 Mon Sep 17 00:00:00 2001
From: "Yuriy M. Kaminskiy" <yum...@gmail.com>
Date: Sat, 24 Mar 2012 22:09:04 +0400
Subject: [PATCH] Fix integer overflow in passing argument to perl function

---
 dbdimp.c               |   15 ++++++++++++++-
 t/09_create_function.t |    6 +++++-
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/dbdimp.c b/dbdimp.c
index 3a4e308..346138c 100644
--- a/dbdimp.c
+++ b/dbdimp.c
@@ -1304,11 +1304,24 @@ sqlite_db_func_dispatcher(int is_unicode, sqlite3_context *context, int argc, sq
         SV *arg;
         STRLEN len;
         int type = sqlite3_value_type(value[i]);
+        sqlite_int64 iv;
 
         /* warn("func dispatch type: %d, value: %s\n", type, sqlite3_value_text(value[i])); */
         switch(type) {
             case SQLITE_INTEGER:
-                arg = sv_2mortal(newSViv(sqlite3_value_int(value[i])));
+                iv = sqlite3_value_int64(value[i]);
+                if ( iv >= IV_MIN && iv <= IV_MAX ) {
+                    /* ^^^ compile-time constant (= true) when IV == int64 */
+                    arg = sv_2mortal(newSViv((IV)iv));
+                }
+                else if ( iv >= 0 && iv <= UV_MAX ) {
+                    /* warn("integer overflow, cast to UV"); */
+                    arg = sv_2mortal(newSVuv((UV)iv));
+                }
+                else {
+                    /* warn("integer overflow, cast to NV"); */
+                    arg = sv_2mortal(newSVnv((NV)iv));
+                }
                 break;
             case SQLITE_FLOAT:
                 arg = sv_2mortal(newSVnv(sqlite3_value_double(value[i])));
diff --git a/t/09_create_function.t b/t/09_create_function.t
index d00e6e6..090fb73 100644
--- a/t/09_create_function.t
+++ b/t/09_create_function.t
@@ -11,7 +11,7 @@ use t::lib::Test qw/connect_ok @CALL_FUNCS/;
 use Test::More;
 use Test::NoWarnings;
 
-plan tests => 27 * @CALL_FUNCS + 1;
+plan tests => 28 * @CALL_FUNCS + 1;
 
 sub now {
     return time();
@@ -119,5 +119,9 @@ foreach my $call_func (@CALL_FUNCS) {
 	$result = $dbh->selectrow_arrayref( "SELECT noop(1.0625)" );
 	is_deeply( $result, [ 1.0625 ], "SELECT noop(1.0625)" );
 
+	# 2147483648 == 1<<31
+	$result = $dbh->selectrow_arrayref( "SELECT noop(2147483648)" );
+	is_deeply( $result, [ 2147483648 ], "SELECT noop(2147483648)" );
+
 	$dbh->disconnect;
 }
-- 
1.7.6.3

_______________________________________________
DBD-SQLite mailing list
DBD-SQLite@lists.scsys.co.uk
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbd-sqlite

Reply via email to