mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/AbuseFilter.git
synced 2024-11-27 23:40:19 +00:00
Avoid implicit casts from DUNDEFINED to something else
This patch keeps the current behaviour for everything (since DUNDEFINED was always casted to boolean false), but handles the cast at a higher level instead of relying on what AFPData::castTypes will do. This way it's easier to spot places where we may get DUNDEFINED, and decide how to handle them one by one. Change-Id: I1070e15ea03c7dd4a4231b87afbc42240a558581
This commit is contained in:
parent
3748c41e79
commit
1fe3647268
|
@ -58,7 +58,7 @@ class AFPData {
|
|||
*/
|
||||
public function __construct( $type, $val = null ) {
|
||||
if ( ( $type === self::DUNDEFINED || $type === self::DEMPTY ) && $val !== null ) {
|
||||
// Sanity, and we rely on this for instance when casting a DUNDEFINED to something else
|
||||
// Sanity
|
||||
throw new InvalidArgumentException( 'DUNDEFINED cannot have a non-null value' );
|
||||
}
|
||||
$this->type = $type;
|
||||
|
@ -111,6 +111,11 @@ class AFPData {
|
|||
if ( $orig->type === $target ) {
|
||||
return $orig->dup();
|
||||
}
|
||||
if ( $orig->type === self::DUNDEFINED ) {
|
||||
// This case should be handled at a higher level, to avoid implicitly relying on what
|
||||
// this method will do for the specific case.
|
||||
throw new AFPException( 'Refusing to cast DUNDEFINED to something else' );
|
||||
}
|
||||
if ( $target === self::DNULL ) {
|
||||
// We don't expose any method to cast to null. And, actually, should we?
|
||||
return new AFPData( self::DNULL );
|
||||
|
@ -340,8 +345,9 @@ class AFPData {
|
|||
* @throws AFPException
|
||||
*/
|
||||
public static function boolOp( AFPData $a, AFPData $b, $op ) {
|
||||
$a = $a->toBool();
|
||||
$b = $b->toBool();
|
||||
$a = $a->type === self::DUNDEFINED ? false : $a->toBool();
|
||||
$b = $b->type === self::DUNDEFINED ? false : $b->toBool();
|
||||
|
||||
if ( $op === '|' ) {
|
||||
return new AFPData( self::DBOOL, $a || $b );
|
||||
} elseif ( $op === '&' ) {
|
||||
|
|
|
@ -63,9 +63,14 @@ class AbuseFilterCachingParser extends AbuseFilterParser {
|
|||
}
|
||||
);
|
||||
|
||||
return $tree
|
||||
$res = $tree
|
||||
? $this->evalNode( $tree )
|
||||
: new AFPData( AFPData::DNULL, null );
|
||||
|
||||
if ( $res->getType() === AFPData::DUNDEFINED ) {
|
||||
$res = new AFPData( AFPData::DBOOL, false );
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -245,7 +250,7 @@ class AbuseFilterCachingParser extends AbuseFilterParser {
|
|||
case AFPTreeNode::LOGIC:
|
||||
list( $op, $leftOperand, $rightOperand ) = $node->children;
|
||||
$leftOperand = $this->evalNode( $leftOperand );
|
||||
$value = $leftOperand->toBool();
|
||||
$value = $leftOperand->getType() === AFPData::DUNDEFINED ? false : $leftOperand->toBool();
|
||||
// Short-circuit.
|
||||
if ( ( !$value && $op === '&' ) || ( $value && $op === '|' ) ) {
|
||||
if ( $rightOperand instanceof AFPTreeNode ) {
|
||||
|
|
|
@ -307,6 +307,10 @@ class AbuseFilterParser {
|
|||
$result = new AFPData( AFPData::DEMPTY );
|
||||
$this->doLevelEntry( $result );
|
||||
|
||||
if ( $result->getType() === AFPData::DUNDEFINED ) {
|
||||
$result = new AFPData( AFPData::DBOOL, false );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -560,9 +564,10 @@ class AbuseFilterParser {
|
|||
$op = $this->mCur->value;
|
||||
$this->move();
|
||||
$r2 = new AFPData( AFPData::DEMPTY );
|
||||
$curVal = $result->getType() === AFPData::DUNDEFINED ? false : $result->toBool();
|
||||
|
||||
// We can go on quickly as either one statement with | is true or one with & is false
|
||||
if ( ( $op === '&' && !$result->toBool() ) || ( $op === '|' && $result->toBool() ) ) {
|
||||
if ( ( $op === '&' && !$curVal ) || ( $op === '|' && $curVal ) ) {
|
||||
$orig = $this->mShortCircuit;
|
||||
$this->mShortCircuit = $this->mAllowShort;
|
||||
$this->doLevelCompares( $r2 );
|
||||
|
@ -570,7 +575,7 @@ class AbuseFilterParser {
|
|||
$this->logEmptyOperand( 'bool operand', __METHOD__ );
|
||||
}
|
||||
$this->mShortCircuit = $orig;
|
||||
$result = new AFPData( AFPData::DBOOL, $result->toBool() );
|
||||
$result = new AFPData( AFPData::DBOOL, $curVal );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue