[wp-trac] [WordPress Trac] #19861: $wpdb->prepare() fails with localized floats
WordPress Trac
wp-trac at lists.automattic.com
Wed Feb 1 22:16:09 UTC 2012
#19861: $wpdb->prepare() fails with localized floats
--------------------------+------------------------------
Reporter: laotse | Owner:
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Database | Version:
Severity: normal | Resolution:
Keywords: |
--------------------------+------------------------------
Comment (by laotse):
I did convert my solution to a patch for the core function. However, there
seem to be bugs in other parts of Wordpress, which pop up on this less
tolerant solution. Obviously, some queries are generated with less format
characters than arguments. Although I made my code somewhat more tolerant
for this error, I still see various errors.
I read the instructions about how to set up a test environment and perform
unit tests. Something I would be able to do, but currently lack the time.
So if someone, who has this all set up and has experience in using it
would apply the patch and tell me about the results, I'd gladly assist in
hunting bugs.
Since I did not see any instructions as to where to upload my patch, I
include it in this comment. The patch does 2 things. It defines a
debugging function 'debug_log' in wp-config.php. This is just debugging
and shall be removed later or be replaced by some canonical mechanism, if
it exists. The other change is the replacement for wpdb::prepare().
{{{
diff --git a/wp-config.php b/wp-config.php
index 8a883bf..c24267d 100644
--- a/wp-config.php
+++ b/wp-config.php
@@ -111,7 +113,20 @@ define ('WPLANG', 'de_DE');
* It is strongly recommended that plugin and theme developers use
WP_DEBUG
* in their development environments.
*/
-define('WP_DEBUG', false);
+define('WP_DEBUG', true);
+if(WP_DEBUG === true){
+ define('WP_DEBUG_DISPLAY', false);
+ define('WP_DEBUG_LOG', true);
+ function debug_log( $mMessage ){
+ if( is_array( $mMessage ) || is_object( $mMessage )){
+ error_log( print_r( $mMessage, true ));
+ } else {
+ error_log( $mMessage );
+ }
+ }
+} else {
+ function debug_log($mMessage) {}
+}
/* That's all, stop editing! Happy blogging. */
diff --git a/wp-content/themes/tantra/header.php b/wp-
content/themes/tantra/header.php
index 817c3e0..e3417e5 100644
--- a/wp-includes/wp-db.php
+++ b/wp-includes/wp-db.php
@@ -890,7 +890,7 @@ class wpdb {
*/
function prepare( $query = null ) { // ( $query, *$args )
if ( is_null( $query ) )
- return;
+ return null;
$args = func_get_args();
array_shift( $args );
@@ -899,9 +899,92 @@ class wpdb {
$args = $args[0];
$query = str_replace( "'%s'", '%s', $query ); // in case
someone mistakenly already singlequoted it
$query = str_replace( '"%s"', '%s', $query ); //
doublequote unquoting
- $query = preg_replace( '|(?<!%)%s|', "'%s'", $query ); //
quote the strings, avoiding escaped strings like %%s
- array_walk( $args, array( &$this, 'escape_by_ref' ) );
- return @vsprintf( $query, $args );
+ $aParts = preg_split('/(%[^%])/', $query, null,
PREG_SPLIT_DELIM_CAPTURE);
+ $sResult = "";
+ $pValue = null;
+ foreach ($aParts as $sPart){
+ if(mb_strlen($sPart) != 2 || $sPart[0] != "%"){
+ // literal string to copy
+ $sResult .= $sPart;
+ } else {
+ if(count($args) <= 0){
+ // ran out of arguments
+ debug_log(__FILE__ . " (" .
__LINE__ . ") wpdb::prepare(): provided more format codes than
arguments!");
+ return false;
+ }
+ $mArg = array_shift($args);
+ switch($sPart[1]) {
+ // %% cannot happen due to the
delimiter pattern
+ default:
+ debug_log(__FILE__ . " ("
. __LINE__ . ") wpdb::prepare(): unknown qualifier '".$sPart."'!");
+ // unknown qualifier
+ return false;
+ case 's':
+ if(!is_null($mArg) &&
!is_string($mArg)){
+ return false;
+ }
+ $sResult .=
(is_null($mArg))? 'NULL' : "'" . $this->_real_escape($mArg) . "'";
+ break;
+ case 'd':
+ if(!is_null($mArg) &&
is_string($mArg)){
+
if(!preg_match('/^\d+$/',$mArg)){
+ // string
is not an integer representation
+
debug_log(__FILE__ . " (" . __LINE__ . ") wpdb::prepare(): string
'".$mArg."' is no integer!");
+ return
false;
+ }
+ $mArg =
intval($mArg);
+ }
+ if(!is_null($mArg) &&
!is_int($mArg)){
+ // parameter is
not int
+ debug_log(__FILE__
. " (" . __LINE__ . ") wpdb::prepare(): parameter is no integer!");
+ return false;
+ }
+ $sResult .=
(is_null($mArg))? 'NULL' : sprintf("%d",$mArg);
+ break;
+ case 'f':
+ if(!is_null($mArg) &&
is_string($mArg)){
+
if(!is_string($pLValue)){
+ // lazy
initialization of a pattern for matching localized floats
+ $aLocale =
localeconv();
+ $pSep =
($aLocale['mon_thousands_sep'] == '.')? '\.' :
$aLocale['mon_thousands_sep'];
+ $pDot =
($aLocale['mon_decimal_point'] == '.')? '\.' :
$aLocale['mon_decimal_point'];
+ $pLValue =
'/^(:?\d+(:?'.$pSep.'\d+)*(:?'.$pDot.'\d*)?|'.$pDot.'\d+)$/';
+ }
+
if(preg_match($pLValue,$mArg)){
+ // looks
like a server locale formatted float string
+ // we have
$aLocale, since we have $pLValue!
+ $mArg =
str_replace($aLocale['mon_thousands_sep'], '', $mArg);
+ $mArg =
str_replace($aLocale['mon_decimal_point'], '.', $mArg);
+ $mArg =
floatval($mArg);
+ }
elseif(preg_match('/^(:?\d+(:?\.\d*)|\.\d+)$/',$mArg)){
+ // looks
like an internal float string
+ $mArg =
floatval($mArg);
+ } else {
+ // looks
pretty unknown
+
debug_log(__FILE__ . " (" . __LINE__ . ") wpdb::prepare(): string
'".$mArg."' is no float!");
+ return
false;
+ }
+ }
+ if(!is_null($mArg) &&
!is_float($mArg)){
+ // this is no
float
+ debug_log(__FILE__
. " (" . __LINE__ . ") wpdb::prepare(): parameter is no float!");
+ return false;
+ }
+ // SQL necessarily
requires a decimal dot and no 1000 seps
+ // %F is expected to
provide this format
+ $sResult .=
(is_null($mArg))? 'NULL' : sprintf("%F",$mArg);
+ break;
+ } // end switch(qualifier)
+ } // end if(string or qualifier)
+ } // end foreach
+ // check consistence
+ if(count($args) > 0){
+ // more arguments than format codes
+ debug_log(__FILE__ . " (" . __LINE__ . ")
wpdb::prepare(): provided less format codes than arguments in query:
'".$query."'");
+ // should strictly be false, but some core
functions are broken!
+ return $sResult;
+ }
+ return $sResult;
}
/**
}}}
--
Ticket URL: <http://core.trac.wordpress.org/ticket/19861#comment:3>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software
More information about the wp-trac
mailing list