Fixing an Operator Precedence Bug in Drupal Core
Today I contributed a fix for a subtle but impactful operator precedence bug in Drupal Core's DefaultTableMapping class. The bug affects how SQL table names are constructed when a database prefix is used and entity type tables are not explicitly configured.
The Problem
In PHP, the concatenation operator (.) has higher precedence than the ternary operator (?:). This led to an issue in the DefaultTableMapping constructor:
$this->baseTable = $this->prefix . $entity_type->getBaseTable() ?: $entity_type->id();
When a prefix is present (e.g., 'prefix_') and getBaseTable() returns NULL, the expression evaluates as follows:
'prefix_' . NULLresults in'prefix_'.'prefix_' ?: $entity_type->id()checks if'prefix_'is truthy.- Since
'prefix_'is truthy, it is returned, and the fallback entity ID is ignored.
This results in a table name that is just the prefix, leading to malformed SQL queries.
The Fix
The fix is straightforward: wrap the ternary expression in parentheses to ensure it is evaluated before concatenation.
$this->baseTable = $this->prefix . ($entity_type->getBaseTable() ?: $entity_type->id());
Verification
I've created a standalone reproduction project with a PHPUnit test to verify the fix. The test ensures that table names are correctly constructed even when getBaseTable() and related methods return NULL.
View Code
Issue Link
