Package Constant: Check missing dsc_address instead of dsc_dtype and restore impure after using existing request#9065
Conversation
… using existing request
|
Execution nodes are supposed to reserve space in impure area using |
| csb->csb_node->pass1(tdbb, csb); | ||
| csb->csb_node->pass2(tdbb, csb); | ||
|
|
||
| if (request == nullptr) |
There was a problem hiding this comment.
When is this function called with null request and when is it called with not null request?
There was a problem hiding this comment.
With request: when executing ReferenceNode.
Without request: when performing a packet scan (without minican) in metacache.
I will add a comment to clearify it
There was a problem hiding this comment.
BTW - why not save descriptor for getDesc() in a cache? I.e. move almost all code from getDesc() to scan().
There was a problem hiding this comment.
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.
| { | ||
| // 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); | ||
| } |
There was a problem hiding this comment.
This whole thing is looking as a complete hack for me.
There was a problem hiding this comment.
Got it. I just wanted to save time. I'll do it the right way
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
Original report: https://groups.google.com/g/firebird-devel/c/uPpRhaAKT0M
In the
makeValuefunction, the value is compiled only once and then cached. Previously, thedsc_addresswas 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 topass1andpass2were 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: