Skip to content
/ server Public

MDEV-31632 Unresolvable outer reference causes null pointer exception#4513

Merged
mariadb-RexJohnston merged 1 commit into10.11from
10.11-MDEV-31632
Jan 22, 2026
Merged

MDEV-31632 Unresolvable outer reference causes null pointer exception#4513
mariadb-RexJohnston merged 1 commit into10.11from
10.11-MDEV-31632

Conversation

@mariadb-RexJohnston
Copy link
Member

SELECT 1 union select 2 UNION SELECT 1 from a JOIN a b ON
  (SELECT 1 FROM dual WHERE AAA)

Crashes during fix_outer_field while resolving field item AAA

In our resolver, once we have determined that a field item isn't
local to our select, we call Item::fix_outer_field(), which
iterates outwards towards the top level select, looking for where
our Item_field might be resolvable.

In our example here, the item isn't resolvable and we expose
fragility in the loop, which i will detail here.

After we initialize the variable 'outer_context' (to a context
containing /* select#3 */ select 1 AS `1` from (a join a b on
((subquery#4))) ) we enter a loop

│     5927   for (;
│     5928        outer_context;
│     5929        outer_context= outer_context->outer_context)
│     5930   {
│     5931     select= outer_context->select_lex;
│     5932     Item_subselect *prev_subselect_item=
│     5933       last_checked_context->select_lex->master_unit()->item;
│     5934     last_checked_context= outer_context;

here 'last_checked_context' is the context inner to the current
'outer_context', and we initialize prev_subselect_item to the
Item enclosing the unit containing this inner select.

So for the first iteration of the loop,
  select: select #3
  last_checked_context: from select #4 to select #3.
  prev_subselect_item: item enclosing select #4 (where
    field item AAA is defined)

The rest of the loop calls find_field_in_tables() /
resolve_ref_in_select_and_group() in an attempt to
resolve this item with this 'outer_context'.

After the item fails resolution, we move to an outer context
  select: select #4294967295 (fake_select_lex)
  last_checked_context: from select #3 to the fake select lex
    containing the union (i.e. outermost)
  prev_subselect_item: null, there is no Item that contains this,
    it is the outermost select.

We still need to execute the rest of the loop to determine whether
AAA is resolvable here, but executing

│     5937     place= prev_subselect_item->parsing_place;

We are now following a null pointer.  We introduce a test for this
null pointer, indicating that we are now evaluating the outermost
select and we are not to try accessing the enclosing subselect item.

Approved by: Oleksandr "Sanja" Byelkin (sanja@mariadb.com)
@mariadb-RexJohnston mariadb-RexJohnston enabled auto-merge (rebase) January 22, 2026 18:44
@mariadb-RexJohnston mariadb-RexJohnston merged commit b061b5a into 10.11 Jan 22, 2026
15 of 17 checks passed
@mariadb-RexJohnston mariadb-RexJohnston deleted the 10.11-MDEV-31632 branch January 22, 2026 19:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants