| @@ -1216,14 +1216,35 @@ | ||
| 1216 | 1216 | $var = trim( (string) $var ); |
| 1217 | 1217 | if( ! strlen( (string) $var ) ) return []; |
| 1218 | 1218 | } |
| 1219 | 1219 | if( is_serialized( $var ) ) { |
| 1220 | - $var = unserialize( $var ); | |
| 1220 | + // This value can come straight from the request: the field state is | |
| 1221 | + // rebuilt from POST, and prepare_args() HTML-decodes it first, so an | |
| 1222 | + // entity-encoded payload arrives here fully restored. Never | |
| 1223 | + // instantiate classes, and never let one through as a value. | |
| 1224 | + $decoded = unserialize( $var, [ 'allowed_classes' => false ] ); | |
| 1225 | + if( is_array( $decoded ) ) { | |
| 1226 | + $var = $decoded; | |
| 1227 | + } elseif( is_scalar( $decoded ) ) { | |
| 1228 | + $var = [ $decoded ]; | |
| 1229 | + } else { | |
| 1230 | + return []; | |
| 1231 | + } | |
| 1221 | 1232 | } elseif( is_scalar( $var ) && strpos( (string) $var, $sep ) !== false ) { |
| 1222 | 1233 | $var = explode( $sep, $var ); |
| 1223 | 1234 | } |
| 1224 | - | |
| 1225 | - return array_map( 'trim', (array) $var ); | |
| 1235 | + | |
| 1236 | + // A multi-choice field value is a flat list of scalars. Only arrays and | |
| 1237 | + // objects are dropped, which a crafted payload can nest here and which | |
| 1238 | + // are a TypeError in trim() on PHP 8. Every other type is cast exactly | |
| 1239 | + // as trim() used to coerce it, so null and bool values are unchanged. | |
| 1240 | + $values = []; | |
| 1241 | + foreach( (array) $var as $key => $value ) { | |
| 1242 | + if( is_array( $value ) || is_object( $value ) ) continue; | |
| 1243 | + $values[ $key ] = trim( (string) $value ); | |
| 1244 | + } | |
| 1245 | + | |
| 1246 | + return $values; | |
| 1226 | 1247 | } |
| 1227 | 1248 | |
| 1228 | 1249 | public function build_array_using_string_rows( $string, $regexp = '' ) { |
| 1229 | 1250 | if( is_scalar( $string ) ) { |