Commit:    30e0442c549bd20288ca8754daa0cdf24d98f055
Author:    Adam Harvey <ahar...@php.net>         Sun, 22 Sep 2013 16:46:17 -0700
Parents:   cc66eaa04b123bdfb6aaa7305713fa508640999e
Branches:  PHP-5.4 PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=30e0442c549bd20288ca8754daa0cdf24d98f055

Log:
Copy dba_*() keys before converting to string.

A nice Sunday afternoon project for somebody would be to refactor the dba
functions to use zend_parse_parameters() reliably and try to untangle some of
the macros in dba.c. Sadly, it is not a nice Sunday afternoon here.

Fixes bug #65708 (dba functions cast $key param to string in-place, bypassing
copy on write).

Bugs:
https://bugs.php.net/65708

Changed paths:
  M  NEWS
  M  ext/dba/dba.c
  A  ext/dba/tests/bug65708.phpt


Diff:
diff --git a/NEWS b/NEWS
index bb170e7..e176325 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,10 @@ PHP                                                          
              NEWS
   . Fixed bug #64157 (DateTime::createFromFormat() reports confusing error
     message). (Boro Sitnikovski)
 
+- DBA extension:
+  . Fixed bug #65708 (dba functions cast $key param to string in-place,
+    bypassing copy on write). (Adam)
+
 - Filter:
   . Add RFC 6598 IPs to reserved addresses. (Sebastian Nohn)
   . Fixed bug #64441 (FILTER_VALIDATE_URL rejects fully qualified domain 
names).
diff --git a/ext/dba/dba.c b/ext/dba/dba.c
index 8005101..50a94dd 100644
--- a/ext/dba/dba.c
+++ b/ext/dba/dba.c
@@ -226,12 +226,17 @@ static size_t php_dba_make_key(zval *key, char **key_str, 
char **key_free TSRMLS
                *key_free = *key_str;
                return len;
        } else {
-               *key_free = NULL;
+               zval tmp = *key;
+               int len;
 
-               convert_to_string(key);
-               *key_str = Z_STRVAL_P(key);
+               zval_copy_ctor(&tmp);
+               convert_to_string(&tmp);
 
-               return Z_STRLEN_P(key);
+               *key_free = *key_str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
+               len = Z_STRLEN(tmp);
+
+               zval_dtor(&tmp);
+               return len;
        }
 }
 /* }}} */
@@ -297,6 +302,14 @@ static size_t php_dba_make_key(zval *key, char **key_str, 
char **key_free TSRMLS
                RETURN_FALSE; \
        }
 
+/* the same check, but with a call to DBA_ID_DONE before returning */
+#define DBA_WRITE_CHECK_WITH_ID \
+       if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != 
DBA_CREAT) { \
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "You cannot perform 
a modification to a database without proper access"); \
+               DBA_ID_DONE; \
+               RETURN_FALSE; \
+       }
+
 /* }}} */
 
 /* {{{ globals */
@@ -557,7 +570,7 @@ static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, 
int mode)
 
        DBA_FETCH_RESOURCE(info, &id);
 
-       DBA_WRITE_CHECK;
+       DBA_WRITE_CHECK_WITH_ID;
 
        if (info->hnd->update(info, key_str, key_len, val, val_len, mode 
TSRMLS_CC) == SUCCESS) {
                DBA_ID_DONE;
@@ -1110,7 +1123,7 @@ PHP_FUNCTION(dba_delete)
 {
        DBA_ID_GET2;
        
-       DBA_WRITE_CHECK;
+       DBA_WRITE_CHECK_WITH_ID;
        
        if(info->hnd->delete(info, key_str, key_len TSRMLS_CC) == SUCCESS)
        {
diff --git a/ext/dba/tests/bug65708.phpt b/ext/dba/tests/bug65708.phpt
new file mode 100644
index 0000000..b77138f
--- /dev/null
+++ b/ext/dba/tests/bug65708.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Bug #65708 (dba functions cast $key param to string in-place, bypassing copy 
on write)
+--SKIPIF--
+<?php 
+       require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+require_once(dirname(__FILE__) .'/test.inc');
+
+$db = dba_popen($db_filename, 'c');
+
+$key = 1;
+$copy = $key;
+
+echo gettype($key)."\n";
+echo gettype($copy)."\n";
+
+dba_exists($key, $db);
+
+echo gettype($key)."\n";
+echo gettype($copy)."\n";
+
+dba_close($db);
+
+?>
+--CLEAN--
+<?php 
+       require(dirname(__FILE__) .'/clean.inc'); 
+?>
+--EXPECT--
+integer
+integer
+integer
+integer


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to