From d1e68ec4cc344a79e5cdbf84adffab9225fc21ba Mon Sep 17 00:00:00 2001 From: Bharanee Rathna Date: Sun, 22 Mar 2015 20:12:04 +1100 Subject: [PATCH] fix uuid overflow in prepared statement id generation. --- .gitmodules | 3 + CHANGELOG | 4 ++ README.md | 12 ++++ Rakefile | 2 +- ext/swift/db/postgres/common.c | 7 ++- ext/swift/db/postgres/datetime.c | 100 +------------------------------ ext/swift/db/postgres/datetime.h | 9 +-- swift-db-postgres.gemspec | Bin 1645 -> 1730 bytes test/test_async.rb | 19 +++--- vendor/swift-db-datetime | 1 + 10 files changed, 37 insertions(+), 120 deletions(-) create mode 100644 .gitmodules mode change 100644 => 120000 ext/swift/db/postgres/datetime.c mode change 100644 => 120000 ext/swift/db/postgres/datetime.h create mode 160000 vendor/swift-db-datetime diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a440714 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vendor/swift-db-datetime"] + path = vendor/swift-db-datetime + url = https://github.com/deepfryed/swift-db-datetime.git diff --git a/CHANGELOG b/CHANGELOG index 359b42c..40199a2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +== 0.3.1 (2015-03-22) + +* prepared statement uuid overflow fix. + == 0.3.0 (2013-02-19) * supports encoding option while connecting. diff --git a/README.md b/README.md index 8e34503..b932294 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,18 @@ MRI adapter for PostgreSQL * Asynchronous support using PQsendQuery family of functions * Nested transactions +## Requirements + +* postgresql client deveopment libraries (libpq-dev) +* uuid development libraries (uuid-dev) + +## Building + +``` +git submodule update --init +rake +``` + ## API ``` diff --git a/Rakefile b/Rakefile index 9ea5ced..267af39 100644 --- a/Rakefile +++ b/Rakefile @@ -7,7 +7,7 @@ require 'rake/testtask' $rootdir = Pathname.new(__FILE__).dirname $gemspec = Gem::Specification.new do |s| s.name = 'swift-db-postgres' - s.version = '0.3.0' + s.version = '0.3.1' s.date = Date.today s.authors = ['Bharanee Rathna'] s.email = ['deepfryed@gmail.com'] diff --git a/ext/swift/db/postgres/common.c b/ext/swift/db/postgres/common.c index be131b4..b314334 100644 --- a/ext/swift/db/postgres/common.c +++ b/ext/swift/db/postgres/common.c @@ -12,11 +12,12 @@ VALUE rb_uuid_string() { char uuid_hex[sizeof(uuid_t) * 2 + 1]; uuid_generate(uuid); + + memset(uuid_hex, 0, sizeof(uuid_hex)); for (n = 0; n < sizeof(uuid_t); n++) - sprintf(uuid_hex + n * 2 + 1, "%02x", uuid[n]); + sprintf(uuid_hex + n * 2, "%02x", uuid[n]); - uuid_hex[0] = 'u'; - return rb_str_new(uuid_hex, sizeof(uuid_t) * 2 + 1); + return rb_str_new(uuid_hex, sizeof(uuid_t) * 2); } /* NOTE: very naive, no regex etc. */ diff --git a/ext/swift/db/postgres/datetime.c b/ext/swift/db/postgres/datetime.c deleted file mode 100644 index a1147ac..0000000 --- a/ext/swift/db/postgres/datetime.c +++ /dev/null @@ -1,99 +0,0 @@ -#include "datetime.h" -#include - -extern VALUE dtformat; - -VALUE cSwiftDateTime, day_seconds; -ID fcivil, fparse, fstrptime; - -// NOTE: only parses '%F %T.%N %z' format and falls back to the built-in DateTime#parse -// and is almost 2x faster than doing: -// -// rb_funcall(klass, fstrptime, 2, rb_str_new(data, size), dtformat); -// -VALUE datetime_parse(VALUE klass, const char *data, size_t size) { - struct tm tm; - double seconds; - const char *ptr; - char tzsign = 0, fraction[32]; - int tzhour = 0, tzmin = 0, lastmatch = -1, offset = 0, idx; - - memset(&tm, 0, sizeof(struct tm)); - sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d%n", - &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &lastmatch); - - // fallback to default datetime parser, this is more expensive. - if (tm.tm_mday == 0) - return Qnil; - - seconds = tm.tm_sec; - - // parse millisecs if any -- tad faster than using %lf in sscanf above. - if (lastmatch > 0 && lastmatch < (int)size && *(data + lastmatch) == '.') { - idx = 0; - ptr = data + ++lastmatch; - while (*ptr && isdigit(*ptr) && idx < 31) { - lastmatch++; - fraction[idx++] = *ptr++; - } - - fraction[idx] = 0; - seconds += (double)atoll(fraction) / pow(10, idx); - } - - // parse timezone offsets if any - matches +HH:MM +HH MM +HHMM - if (lastmatch > 0 && lastmatch < (int)size) { - const char *ptr = data + lastmatch; - while(*ptr && *ptr != '+' && *ptr != '-') ptr++; - tzsign = *ptr++; - if (*ptr && isdigit(*ptr)) { - tzhour = *ptr++ - '0'; - if (*ptr && isdigit(*ptr)) tzhour = tzhour * 10 + *ptr++ - '0'; - while(*ptr && !isdigit(*ptr)) ptr++; - if (*ptr) { - tzmin = *ptr++ - '0'; - if (*ptr && isdigit(*ptr)) tzmin = tzmin * 10 + *ptr++ - '0'; - } - } - } - - if (tzsign) { - offset = tzsign == '+' - ? (time_t)tzhour * 3600 + (time_t)tzmin * 60 - : (time_t)tzhour * -3600 + (time_t)tzmin * -60; - } - - return rb_funcall(klass, fcivil, 7, - INT2FIX(tm.tm_year), INT2FIX(tm.tm_mon), INT2FIX(tm.tm_mday), - INT2FIX(tm.tm_hour), INT2FIX(tm.tm_min), DBL2NUM(seconds), - offset == 0 ? INT2FIX(0) : rb_Rational(INT2FIX(offset), day_seconds) - ); -} - -VALUE rb_datetime_parse(VALUE self, VALUE string) { - VALUE datetime; - const char *data = CSTRING(string); - size_t size = TYPE(string) == T_STRING ? (size_t)RSTRING_LEN(string) : strlen(data); - - if (NIL_P(string)) - return Qnil; - - datetime = datetime_parse(self, data, size); - return NIL_P(datetime) ? rb_call_super(1, &string) : datetime; -} - -void init_swift_datetime() { - VALUE mSwift, cDateTime; - - rb_require("date"); - mSwift = rb_define_module("Swift"); - cDateTime = CONST_GET(rb_mKernel, "DateTime"); - cSwiftDateTime = rb_define_class_under(mSwift, "DateTime", cDateTime); - fcivil = rb_intern("civil"); - fparse = rb_intern("parse"); - fstrptime = rb_intern("strptime"); - day_seconds = INT2FIX(86400); - - rb_global_variable(&day_seconds); - rb_define_singleton_method(cSwiftDateTime, "parse", RUBY_METHOD_FUNC(rb_datetime_parse), 1); -} diff --git a/ext/swift/db/postgres/datetime.c b/ext/swift/db/postgres/datetime.c new file mode 120000 index 0000000..37f1e6c --- /dev/null +++ b/ext/swift/db/postgres/datetime.c @@ -0,0 +1 @@ +../../../../vendor/swift-db-datetime/src/swift/db/datetime.c \ No newline at end of file diff --git a/ext/swift/db/postgres/datetime.h b/ext/swift/db/postgres/datetime.h deleted file mode 100644 index 793dc87..0000000 --- a/ext/swift/db/postgres/datetime.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "common.h" -#include - -DLL_PRIVATE extern VALUE cSwiftDateTime; -DLL_PRIVATE void init_swift_datetime(); -DLL_PRIVATE VALUE datetime_parse(VALUE klass, const char *data, size_t size); diff --git a/ext/swift/db/postgres/datetime.h b/ext/swift/db/postgres/datetime.h new file mode 120000 index 0000000..9dfeac4 --- /dev/null +++ b/ext/swift/db/postgres/datetime.h @@ -0,0 +1 @@ +../../../../vendor/swift-db-datetime/src/swift/db/datetime.h \ No newline at end of file diff --git a/swift-db-postgres.gemspec b/swift-db-postgres.gemspec index 667e3a7bcb7a6e0ecb926860884130aa535731b6..d818c512481c9f4a316ab7e1ea276625db7de955 100644 GIT binary patch delta 269 zcmaFMbBK3>l&P{paY<>Cl|pfOW?G4EN|J6tesM{9QEIV*fu6CRp+Zqf)U&dG0p{8^0LlM|UF zCu=gxPp)E8nEakm35eMz^DzVEm{ft7YjO~fy`PD5vMo^kekQ)jo-8txby;M%OHzwV z^fOX(3Q~(EpJmpZ%+De?`6II&TXAuYUQyEIY8Lm&Pg#Unjr5H43?~0$DQ7g9T*mqx E0A!w1^#A|> delta 210 zcmV;@04@K*4ebn&8j)~O0Wgumag$a7EeA6#FfuJMIg^S3q?6JDI+K$FB9mSMBa