Make WordPress Core

Changeset 54100


Ignore:
Timestamp:
09/08/2022 01:24:10 PM (2 years ago)
Author:
SergeyBiryukov
Message:

KSES: Allow min(), max(), minmax(), and clamp() values to be used in inline CSS.

Additionally, this commit updates safecss_filter_attr() to add support for nested var() functions, so that a fallback value can be another CSS variable.

Follow-up to [50923].

Props johnregan3, noisysocks, cbravobernal, uxl, isabel_brison, andrewserong, ramonopoly, joyously, bernhard-reiter, peterwilsoncc.
Fixes #55966.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/kses.php

    r54093 r54100  
    22292229 * @since 5.7.1 Added support for `object-position`.
    22302230 * @since 5.8.0 Added support for `calc()` and `var()` values.
     2231 * @since 6.1.0 Added support for `min()`, `max()`, `minmax()`, `clamp()`,
     2232 *              and nested `var()` values.
    22312233 *
    22322234 * @param string $css        A string of CSS rules.
     
    24682470
    24692471        if ( $found ) {
    2470             // Allow CSS calc().
    2471             $css_test_string = preg_replace( '/calc\(((?:\([^()]*\)?|[^()])*)\)/', '', $css_test_string );
    2472             // Allow CSS var().
    2473             $css_test_string = preg_replace( '/\(?var\(--[a-zA-Z0-9_-]*\)/', '', $css_test_string );
    2474 
    2475             // Check for any CSS containing \ ( & } = or comments,
    2476             // except for url(), calc(), or var() usage checked above.
     2472            /*
     2473             * Allow CSS functions like var(), calc(), etc. by removing them from the test string.
     2474             * Nested functions and parentheses are also removed, so long as the parentheses are balanced.
     2475             */
     2476            $css_test_string = preg_replace(
     2477                '/\b(?:var|calc|min|max|minmax|clamp)(\((?:[^()]|(?1))*\))/',
     2478                '',
     2479                $css_test_string
     2480            );
     2481
     2482            /*
     2483             * Disallow CSS containing \ ( & } = or comments, except for within url(), var(), calc(), etc.
     2484             * which were removed from the test string above.
     2485             */
    24772486            $allow_css = ! preg_match( '%[\\\(&=}]|/\*%', $css_test_string );
    24782487
  • trunk/tests/phpunit/tests/kses.php

    r54093 r54100  
    936936     * @ticket 42729
    937937     * @ticket 48376
     938     * @ticket 55966
    938939     * @dataProvider data_test_safecss_filter_attr
    939940     *
     
    11211122                'expected' => '',
    11221123            ),
     1124            // Allow min().
     1125            array(
     1126                'css'      => 'width: min(50%, 400px)',
     1127                'expected' => 'width: min(50%, 400px)',
     1128            ),
     1129            // Allow max().
     1130            array(
     1131                'css'      => 'width: max(50%, 40rem)',
     1132                'expected' => 'width: max(50%, 40rem)',
     1133            ),
     1134            // Allow minmax().
     1135            array(
     1136                'css'      => 'width: minmax(100px, 50%)',
     1137                'expected' => 'width: minmax(100px, 50%)',
     1138            ),
     1139            // Allow clamp().
     1140            array(
     1141                'css'      => 'width: clamp(100px, 50%, 100vw)',
     1142                'expected' => 'width: clamp(100px, 50%, 100vw)',
     1143            ),
     1144            // Allow two functions in the same CSS.
     1145            array(
     1146                'css'      => 'width: clamp(min(100px, 350px), 50%, 500px), 600px)',
     1147                'expected' => 'width: clamp(min(100px, 350px), 50%, 500px), 600px)',
     1148            ),
     1149            // Allow gradient() function.
     1150            array(
     1151                'css'      => 'background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 35%, rgba(0,212,255,1) 100%)',
     1152                'expected' => 'background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 35%, rgba(0,212,255,1) 100%)',
     1153            ),
     1154            // Combined CSS function names.
     1155            array(
     1156                'css'      => 'width: calcmax(100px + 50%)',
     1157                'expected' => '',
     1158            ),
     1159            // Allow calc().
     1160            array(
     1161                'css'      => 'width: calc(2em + 3px)',
     1162                'expected' => 'width: calc(2em + 3px)',
     1163            ),
     1164            // Allow calc() with nested brackets.
     1165            array(
     1166                'css'      => 'width: calc(3em + (10px * 2))',
     1167                'expected' => 'width: calc(3em + (10px * 2))',
     1168            ),
     1169            // Allow var().
     1170            array(
     1171                'css'      => 'padding: var(--wp-var1) var(--wp-var2)',
     1172                'expected' => 'padding: var(--wp-var1) var(--wp-var2)',
     1173            ),
     1174            // Allow var() with fallback (commas).
     1175            array(
     1176                'css'      => 'padding: var(--wp-var1, 10px)',
     1177                'expected' => 'padding: var(--wp-var1, 10px)',
     1178            ),
     1179            // Allow var() with fallback (percentage).
     1180            array(
     1181                'css'      => 'padding: var(--wp-var1, 50%)',
     1182                'expected' => 'padding: var(--wp-var1, 50%)',
     1183            ),
     1184            // Allow var() with fallback var().
     1185            array(
     1186                'css'      => 'background-color: var(--wp-var, var(--wp-var-fallback, pink))',
     1187                'expected' => 'background-color: var(--wp-var, var(--wp-var-fallback, pink))',
     1188            ),
     1189            // Allow var() with square brackets.
     1190            array(
     1191                'css'      => 'background-color: var(--wp-var, [pink])',
     1192                'expected' => 'background-color: var(--wp-var, [pink])',
     1193            ),
     1194            // Allow calc() with var().
     1195            array(
     1196                'css'      => 'margin-top: calc(var(--wp-var1) * 3 + 2em)',
     1197                'expected' => 'margin-top: calc(var(--wp-var1) * 3 + 2em)',
     1198            ),
     1199            // Malformed min, no closing `)`.
     1200            array(
     1201                'css'      => 'width: min(3em + 10px',
     1202                'expected' => '',
     1203            ),
     1204            // Malformed max, no closing `)`.
     1205            array(
     1206                'css'      => 'width: max(3em + 10px',
     1207                'expected' => '',
     1208            ),
     1209            // Malformed minmax, no closing `)`.
     1210            array(
     1211                'css'      => 'width: minmax(3em + 10px',
     1212                'expected' => '',
     1213            ),
     1214            // Malformed calc, no closing `)`.
     1215            array(
     1216                'css'      => 'width: calc(3em + 10px',
     1217                'expected' => '',
     1218            ),
     1219            // Malformed var, no closing `)`.
     1220            array(
     1221                'css'      => 'width: var(--wp-var1',
     1222                'expected' => '',
     1223            ),
     1224            // Malformed calc, mismatching brackets.
     1225            array(
     1226                'css'      => 'width: calc(3em + (10px * 2)',
     1227                'expected' => '',
     1228            ),
     1229            // Malformed var, mismatching brackets.
     1230            array(
     1231                'css'      => 'background-color: var(--wp-var, var(--wp-var-fallback, pink)',
     1232                'expected' => '',
     1233            ),
     1234            // Don't allow expressions outside of a calc().
     1235            array(
     1236                'css'      => 'width: (3em + (10px * 2))',
     1237                'expected' => '',
     1238            ),
    11231239        );
    11241240    }
     
    13021418            ),
    13031419
    1304             // CSS calc().
    1305             array(
    1306                 'width: calc(2em + 3px)',
    1307                 'width: calc(2em + 3px)',
    1308             ),
    1309 
    1310             // CSS variable.
    1311             array(
    1312                 'padding: var(--wp-var1) var(--wp-var2)',
    1313                 'padding: var(--wp-var1) var(--wp-var2)',
    1314             ),
    1315 
    1316             // CSS calc() with var().
    1317             array(
    1318                 'margin-top: calc(var(--wp-var1) * 3 + 2em)',
    1319                 'margin-top: calc(var(--wp-var1) * 3 + 2em)',
    1320             ),
    1321 
    13221420            /*
    13231421             * Invalid use cases.
     
    13811479            array(
    13821480                'background-image: url( "http://example.com );',
    1383                 '',
    1384             ),
    1385 
    1386             // Malformed calc, no closing `)`.
    1387             array(
    1388                 'width: calc(3em + 10px',
    1389                 '',
    1390             ),
    1391 
    1392             // Malformed var, no closing `)`.
    1393             array(
    1394                 'width: var(--wp-var1',
    13951481                '',
    13961482            ),
  • trunk/tests/phpunit/tests/theme/wpThemeJson.php

    r53129 r54100  
    16031603                        'core/cover'  => array(
    16041604                            'filter' => array(
    1605                                 'duotone' => 'var(--wp--preset--duotone--blue-red, var(--fallback-unsafe))',
     1605                                'duotone' => 'var(--invalid',
    16061606                            ),
    16071607                        ),
     
    16771677                        'radius' => array(
    16781678                            'topLeft'     => '6px',
    1679                             'topRight'    => 'var(--top-right, var(--unsafe-fallback))',
     1679                            'topRight'    => 'var(--invalid',
    16801680                            'bottomRight' => '6px',
    16811681                            'bottomLeft'  => '6px',
     
    16861686                            'top'    => '1px',
    16871687                            'right'  => '1px',
    1688                             'bottom' => 'var(--bottom, var(--unsafe-fallback))',
     1688                            'bottom' => 'var(--invalid',
    16891689                            'left'   => '1px',
    16901690                        ),
     
    16961696                                    'top'    => '2px',
    16971697                                    'right'  => '2px',
    1698                                     'bottom' => 'var(--bottom, var(--unsafe-fallback))',
     1698                                    'bottom' => 'var(--invalid',
    16991699                                    'left'   => '2px',
    17001700                                ),
     
    17071707                                'radius' => array(
    17081708                                    'topLeft'     => '5px',
    1709                                     'topRight'    => 'var(--top-right, var(--unsafe-fallback))',
     1709                                    'topRight'    => 'var(--invalid',
    17101710                                    'bottomRight' => '5px',
    17111711                                    'bottomLeft'  => '5px',
     
    17161716                                    'top'    => '3px',
    17171717                                    'right'  => '3px',
    1718                                     'bottom' => 'var(bottom, var(--unsafe-fallback))',
     1718                                    'bottom' => 'var(--invalid',
    17191719                                    'left'   => '3px',
    17201720                                ),
     
    17261726                                            'top'    => '4px',
    17271727                                            'right'  => '4px',
    1728                                             'bottom' => 'var(--bottom, var(--unsafe-fallback))',
     1728                                            'bottom' => 'var(--invalid',
    17291729                                            'left'   => '4px',
    17301730                                        ),
     
    19451945                                    'name'  => 'Blue',
    19461946                                    'slug'  => 'blue',
    1947                                     'color' => 'var(--color, var(--unsafe-fallback))',
     1947                                    'color' => 'var(--invalid',
    19481948                                ),
    19491949                                array(
     
    19761976                                    'name'       => 'Helvetica Arial',
    19771977                                    'slug'       => 'helvetica-arial',
    1978                                     'fontFamily' => 'var(--fontFamily, var(--unsafe-fallback))',
     1978                                    'fontFamily' => 'var(--invalid',
    19791979                                ),
    19801980                            ),
     
    19991999                                            'name'  => 'Blue',
    20002000                                            'slug'  => 'blue',
    2001                                             'color' => 'var(--color, var(--unsafe--fallback))',
     2001                                            'color' => 'var(--invalid',
    20022002                                        ),
    20032003                                        array(
Note: See TracChangeset for help on using the changeset viewer.