summaryrefslogtreecommitdiff
path: root/ext/pdo_dblib/dblib_stmt.c
diff options
context:
space:
mode:
authorAdam Baratz <adambaratz@php.net>2017-11-10 13:29:14 -0500
committerAdam Baratz <adambaratz@php.net>2017-11-10 13:29:14 -0500
commit01f2427b838d55f8b6837585dadeb16edf4ed02b (patch)
treee2160572c1867b4cb337f8c902ae7dbb9919f36e /ext/pdo_dblib/dblib_stmt.c
parentca1f07b6d733c2f422cb99ffb0e6122b2d5f8b5e (diff)
downloadphp-git-01f2427b838d55f8b6837585dadeb16edf4ed02b.tar.gz
More robust handling of stringified column data
- Use at least the FreeTDS maximum when converting datetime data - Pass buffer length to dbconvert() - Use dbconvert() return value to set string lengths or handle errors - Move shared code into shared function
Diffstat (limited to 'ext/pdo_dblib/dblib_stmt.c')
-rw-r--r--ext/pdo_dblib/dblib_stmt.c65
1 files changed, 46 insertions, 19 deletions
diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c
index 175cb30332..3e4625ee67 100644
--- a/ext/pdo_dblib/dblib_stmt.c
+++ b/ext/pdo_dblib/dblib_stmt.c
@@ -260,7 +260,7 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno)
return 1;
}
-static int pdo_dblib_stmt_stringify_col(pdo_stmt_t *stmt, int coltype)
+static int pdo_dblib_stmt_should_stringify_col(pdo_stmt_t *stmt, int coltype)
{
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
pdo_dblib_db_handle *H = S->H;
@@ -305,6 +305,48 @@ static int pdo_dblib_stmt_stringify_col(pdo_stmt_t *stmt, int coltype)
return 0;
}
+static void pdo_dblib_stmt_stringify_col(int coltype, LPBYTE data, DBINT data_len, zval **ptr)
+{
+ DBCHAR *tmp_data;
+ DBINT tmp_data_len;
+ zval *zv;
+
+ /* FIXME: We allocate more than we need here */
+ tmp_data_len = 32 + (2 * (data_len));
+
+ switch (coltype) {
+ case SQLDATETIME:
+ case SQLDATETIM4: {
+ if (tmp_data_len < DATETIME_MAX_LEN) {
+ tmp_data_len = DATETIME_MAX_LEN;
+ }
+ break;
+ }
+ }
+
+ tmp_data = emalloc(tmp_data_len);
+ data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, (LPBYTE) tmp_data, tmp_data_len);
+
+ zv = emalloc(sizeof(zval));
+ if (data_len > 0) {
+ /* to prevent overflows, tmp_data_len is provided as a dest len for dbconvert()
+ * this code previously passed a dest len of -1
+ * the FreeTDS impl of dbconvert() does an rtrim with that value, so replicate that behavior
+ */
+ while (data_len > 0 && tmp_data[data_len - 1] == ' ') {
+ data_len--;
+ }
+
+ ZVAL_STRINGL(zv, tmp_data, data_len);
+ } else {
+ ZVAL_EMPTY_STRING(zv);
+ }
+
+ efree(tmp_data);
+
+ *ptr = zv;
+}
+
static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
zend_ulong *len, int *caller_frees)
{
@@ -323,15 +365,8 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
data_len = dbdatlen(H->link, colno+1);
if (data_len != 0 || data != NULL) {
- if (pdo_dblib_stmt_stringify_col(stmt, coltype) && dbwillconvert(coltype, SQLCHAR)) {
- tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
- tmp_data = emalloc(tmp_data_len);
- data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, (LPBYTE) tmp_data, -1);
-
- zv = emalloc(sizeof(zval));
- ZVAL_STRING(zv, tmp_data);
-
- efree(tmp_data);
+ if (pdo_dblib_stmt_should_stringify_col(stmt, coltype) && dbwillconvert(coltype, SQLCHAR)) {
+ pdo_dblib_stmt_stringify_col(coltype, data, data_len, &zv);
}
if (!zv) {
@@ -438,7 +473,6 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
zv = emalloc(sizeof(zval));
ZVAL_STRINGL(zv, tmp_data, data_len);
efree(tmp_data);
-
} else {
/* 16-byte binary representation */
zv = emalloc(sizeof(zval));
@@ -449,14 +483,7 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
default: {
if (dbwillconvert(coltype, SQLCHAR)) {
- tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
- tmp_data = emalloc(tmp_data_len);
- data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, (LPBYTE) tmp_data, -1);
-
- zv = emalloc(sizeof(zval));
- ZVAL_STRING(zv, tmp_data);
-
- efree(tmp_data);
+ pdo_dblib_stmt_stringify_col(coltype, data, data_len, &zv);
}
break;