Skip to:
Content

BuddyPress.org

Changeset 9073


Ignore:
Timestamp:
10/08/2014 02:14:29 PM (10 years ago)
Author:
boonebgorges
Message:

Better detection for false positives in meta SQL filters.

Our wrappers for WP's _metadata() functions require some filtering of the SQL
string (to change a column name and, in the case of xprofile, to add an
'object_type' clause). Our str_replace() logic is too generous, creating the
possibility of matching quoted text, as when the meta value contains the string
'WHERE'.

This changeset modifies the filters so that quoted content is swapped out with
placeholders before we run our search-and-replace.

See #5919.
Props tometzky for feedback.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-core/bp-core-filters.php

    r9001 r9073  
    604604 */
    605605function bp_filter_metaid_column_name( $q ) {
    606     return str_replace( 'meta_id', 'id', $q );
     606    /*
     607     * Replace quoted content with __QUOTE__ to avoid false positives.
     608     * This regular expression will match nested quotes.
     609     */
     610    $quoted_regex = "/'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'/s";
     611    preg_match_all( $quoted_regex, $q, $quoted_matches );
     612    $q = preg_replace( $quoted_regex, '__QUOTE__', $q );
     613
     614    $q = str_replace( 'meta_id', 'id', $q );
     615
     616    // Put quoted content back into the string.
     617    if ( ! empty( $quoted_matches[0] ) ) {
     618        for ( $i = 0; $i < count( $quoted_matches[0] ); $i++ ) {
     619            $quote_pos = strpos( $q, '__QUOTE__' );
     620            $q = substr_replace( $q, $quoted_matches[0][ $i ], $quote_pos, 9 );
     621        }
     622    }
     623
     624    return $q;
    607625}
    608626
  • trunk/src/bp-xprofile/bp-xprofile-filters.php

    r8815 r9073  
    336336    global $wpdb;
    337337
     338    $raw_q = $q;
     339
     340    /*
     341     * Replace quoted content with __QUOTE__ to avoid false positives.
     342     * This regular expression will match nested quotes.
     343     */
     344    $quoted_regex = "/'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'/s";
     345    preg_match_all( $quoted_regex, $q, $quoted_matches );
     346    $q = preg_replace( $quoted_regex, '__QUOTE__', $q );
     347
    338348    // Get the first word of the command
    339349    preg_match( '/^(\S+)/', $q, $first_word_matches );
    340350
    341351    if ( empty( $first_word_matches[0] ) ) {
    342         return $q;
     352        return $raw_q;
    343353    }
    344354
     
    347357
    348358    if ( empty( $matches[0] ) || empty( $matches[1] ) ) {
    349         return $q;
     359        return $raw_q;
    350360    }
    351361
     
    416426    }
    417427
     428    // Put quoted content back into the string.
     429    if ( ! empty( $quoted_matches[0] ) ) {
     430        for ( $i = 0; $i < count( $quoted_matches[0] ); $i++ ) {
     431            $quote_pos = strpos( $q, '__QUOTE__' );
     432            $q = substr_replace( $q, $quoted_matches[0][ $i ], $quote_pos, 9 );
     433        }
     434    }
     435
    418436    return $q;
    419437}
  • trunk/tests/phpunit/testcases/xprofile/functions.php

    r8987 r9073  
    474474    /**
    475475     * @group xprofilemeta
     476     * @group bp_xprofile_update_meta
     477     * @ticket BP5919
     478     */
     479    public function test_bp_xprofile_update_meta_where_sql_filter_keywords_are_in_quoted_value() {
     480        $g = $this->factory->xprofile_group->create();
     481        $value = "SELECT object_id FROM wp_bp_xprofile_groups WHERE \"foo\" VALUES (foo = 'bar'";
     482        bp_xprofile_add_meta( $g, 'group', 'foo', 'bar' );
     483        bp_xprofile_update_meta( $g, 'group', 'foo', $value );
     484        $this->assertSame( $value, bp_xprofile_get_meta( $g, 'group', 'foo' ) );
     485    }
     486
     487    /**
     488     * @group xprofilemeta
     489     * @group bp_xprofile_update_meta
     490     * @ticket BP5919
     491     */
     492    public function test_bp_xprofile_update_meta_where_meta_id_is_in_quoted_value() {
     493        $g = $this->factory->xprofile_group->create();
     494        $value = "foo meta_id bar";
     495        bp_xprofile_add_meta( $g, 'group', 'foo', 'bar' );
     496        bp_xprofile_update_meta( $g, 'group', 'foo', $value );
     497        $this->assertSame( $value, bp_xprofile_get_meta( $g, 'group', 'foo' ) );
     498    }
     499
     500    /**
     501     * @group xprofilemeta
    476502     * @group bp_xprofile_add_meta
    477503     */
Note: See TracChangeset for help on using the changeset viewer.