Skip to content

Package Constant: Check missing dsc_address instead of dsc_dtype and restore impure after using existing request#9065

Open
Noremos wants to merge 4 commits into
FirebirdSQL:masterfrom
Noremos:package_invalid_dsc_address_and_impure_usage
Open

Package Constant: Check missing dsc_address instead of dsc_dtype and restore impure after using existing request#9065
Noremos wants to merge 4 commits into
FirebirdSQL:masterfrom
Noremos:package_invalid_dsc_address_and_impure_usage

Conversation

@Noremos

@Noremos Noremos commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Original report: https://groups.google.com/g/firebird-devel/c/uPpRhaAKT0M

In the makeValue function, the value is compiled only once and then cached. Previously, the dsc_address was always present, but now it is not required for calculating the hash, so it may be missing. This leads to null pointer read/write.

The second issue is related with request impure space. First, the calls to pass1 and pass2 were missing, leading to invalid addresses being used. Second, using an existing request, its impure will be corrupt. So, it should be restored after the node is executed.

SQL to reproduce:

shell rm -rf /tmp/test.fdb;
create database ' /tmp/test.fdb';

set bail on;
set list on;
set autoterm on;
set autoddl off;
set keep_tran on;


recreate package pg_test as
begin
    procedure sp_test() returns(o smallint);
end;

recreate package body pg_test as
begin
    constant PG_BODY_CONST smallint = -10;
    procedure sp_test() returns(o smallint) as
    begin
        o = pg_body_const;
        suspend;
    end
end
;
commit;

select p.o as get_pkg_head_const_1  from pg_test.sp_test as p rows 1; -- segfault

@aafemt

aafemt commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Execution nodes are supposed to reserve space in impure area using CompilerScratch::allocImpure during compilation, remember the returned offset and during execution get the address for usage with Request::getImpure.

@Noremos Noremos changed the title Check missing dsc_address instead of dsc_dtype and restore impure after using existing request Package Constant: Check missing dsc_address instead of dsc_dtype and restore impure after using existing request Jun 16, 2026
Comment thread src/jrd/Package.epp Outdated
csb->csb_node->pass1(tdbb, csb);
csb->csb_node->pass2(tdbb, csb);

if (request == nullptr)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is this function called with null request and when is it called with not null request?

@Noremos Noremos Jun 20, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With request: when executing ReferenceNode.
Without request: when performing a packet scan (without minican) in metacache.
I will add a comment to clearify it

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW - why not save descriptor for getDesc() in a cache? I.e. move almost all code from getDesc() to scan().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment about null request

BTW - why not save descriptor for getDesc() in a cache? I.e. move almost all code from getDesc() to scan().

Good point: getDesc queries the descriptor by name, but there's nothing stopping one from getting it via package->findConstant. Especially considering the function is already called when checking for the constant's existence. I'll create a separate PR with this optimization.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR with the improveemnt: #9069

Comment thread src/jrd/Package.epp Outdated
Comment on lines +221 to +241
{
// A csb->csb_node will use impureArea from the incoming request
// but it contains other data
// Backup the current data and restore it later

// Reusing a small chunk is faster instead of makeing a new request
// And using existing space for a temporally value is better instead of adding this to request->impureArea
// and carrying it for whole request live

const auto nodeImpureSize = csb->csb_impure;
if (request->impureArea.getCount() < nodeImpureSize)
request->impureArea.grow(nodeImpureSize - request->impureArea.getCount());

const Array<UCHAR> backup(request->impureArea.begin(), nodeImpureSize);

fb_assert(tdbb->getRequest() == request);
executeCsbNode(tdbb, csb);

// Restore
memcpy(request->impureArea.begin(), backup.begin(), nodeImpureSize);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole thing is looking as a complete hack for me.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. I just wanted to save time. I'll do it the right way

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you not building a statement/request which is standard way to execute code?
There are many things allowed in constants. How you do ensure that all that code and new code is prepared to take that shortcut?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are many things allowed in constants. How you do ensure that all that code and new code is prepared to take that shortcut?

You are right. Now the handmade requset will be used

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants