Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate or transform string of DML queries so that engine internals doesn't receive malformed strings [CORE2724] #3120

Closed
firebird-automations opened this issue Nov 1, 2009 · 6 comments

Comments

@firebird-automations
Copy link
Collaborator

Submitted by: @asfernandes

It has been verified that malformed text of queries may come to engine internals and later be stored in BLOBs without validation.

This situation happened with DDL triggers, and possible happens with monitoring tables too.

The solution adopted depends on the attachment charset used:
- If it's NONE, non-ASCII characters are transformed to question marks
- Otherwise, the string is checked for malformed characters

This happens only for DML. For DDL, it will prevent the command to succeed as before.

Commits: 8c6f98e

@firebird-automations
Copy link
Collaborator Author

Modified by: @asfernandes

status: Open [ 1 ] => Resolved [ 5 ]

resolution: Fixed [ 1 ]

Fix Version: 3.0 Alpha 1 [ 10331 ]

assignee: Adriano dos Santos Fernandes [ asfernandes ]

@firebird-automations
Copy link
Collaborator Author

Modified by: @pcisar

status: Resolved [ 5 ] => Closed [ 6 ]

@firebird-automations
Copy link
Collaborator Author

Modified by: @pavel-zotov

QA Status: No test

@firebird-automations
Copy link
Collaborator Author

Commented by: @pavel-zotov

Is it OK that when we specify charset = NONE and DDL trigger does contain text literals in multi-byte charset (utf8, sample see below) then result can contain _both_ unicode text and question marks ?

Change port/path/filename in following scripts and apply them:

1. Preparing:

shell del C:\\MIX\\firebird\\QA\\fbt\-repo\\tmp\\c2724\.fdb 2\>nul;
set names utf8;
create database '/3333:C:\\MIX\\firebird\\QA\\fbt\-repo\\tmp\\c2724\.fdb' default character set utf8;

create sequence ddl\_seq;

create table ddl\_log \(
    id bigint not null primary key,
    moment timestamp not null,
    user\_name varchar\(31\) not null,
    event\_type varchar\(25\) not null,
    object\_type varchar\(25\) not null,
    ddl\_event varchar\(25\) not null,
    object\_name varchar\(31\) not null,
    old\_object\_name varchar\(31\),
    new\_object\_name varchar\(31\),
    sql\_text blob sub\_type text not null,
    ok char\(1\) not null,
    result\_info blob sub\_type text \-\- the same for 'varchar\(255\)'
\);
commit;

set term ^;
create trigger trig\_ddl\_log\_before before any ddl statement
as
    declare id type of column ddl\_log\.id;
begin
    \-\- We do the changes in an AUTONOMOUS TRANSACTION, so if an exception happens and the command
    \-\- didn't run, the log will survive\.
    in autonomous transaction do
    begin
        insert into ddl\_log \(id, moment, user\_name, event\_type, object\_type, ddl\_event, object\_name,
                             old\_object\_name, new\_object\_name, sql\_text, ok, result\_info\)
            values \(next value for ddl\_seq, current\_timestamp, current\_user,
                    rdb$get\_context\('DDL\_TRIGGER', 'EVENT\_TYPE'\),
                    rdb$get\_context\('DDL\_TRIGGER', 'OBJECT\_TYPE'\),
                    rdb$get\_context\('DDL\_TRIGGER', 'DDL\_EVENT'\),
                    rdb$get\_context\('DDL\_TRIGGER', 'OBJECT\_NAME'\),
                    rdb$get\_context\('DDL\_TRIGGER', 'OLD\_OBJECT\_NAME'\),
                    rdb$get\_context\('DDL\_TRIGGER', 'NEW\_OBJECT\_NAME'\),
                    rdb$get\_context\('DDL\_TRIGGER', 'SQL\_TEXT'\),
                    'N',
                    'Κάτι συνέβη\. Θα πρέπει να ελέγξετε'\) \-\- Something was wrong\. One need to check this\.
            returning id into id;
        rdb$set\_context\('USER\_SESSION', 'trig\_ddl\_log\_id', id\);
    end
end
^

\-\- Note: the above trigger will fire for this DDL command\. It's good idea to use \-nodbtriggers
\-\- when working with them\!
create trigger trig\_ddl\_log\_after after any ddl statement
as
begin
    \-\- Here we need an AUTONOMOUS TRANSACTION because the original transaction will not see the
    \-\- record inserted on the BEFORE trigger autonomous transaction if user transaction is not
    \-\- READ COMMITTED\.
    in autonomous transaction do
        update ddl\_log set ok = 'Y', 
        result\_info = 'Τα πάντα ήταν επιτυχής' \-\- Everything has completed successfully
        where id = rdb$get\_context\('USER\_SESSION', 'trig\_ddl\_log\_id'\);
end
^
set term ;^
commit;

\-\- So lets delete the record about trig\_ddl\_log\_after creation\.
delete from ddl\_log;
commit;

===

2. Script for run (I gave it name = 'c2724-run.sql'):

set names none; \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-  charset  =  \.N\.O\.N\.E\.
connect '/3333:C:\\MIX\\firebird\\QA\\fbt\-repo\\tmp\\c2724\.fdb';    

create domain dm\_name varchar\(50\) check \(value in \('αμορτισέρ', 'κόμβο', 'σωλήνα', 'φέροντα', 'βραχίονα'\)\);

\-\- This will be logged one time \(as T1 did not exist, RECREATE acts as CREATE\) with OK = Y\.
recreate table t1 \(
     saller\_id integer  \-\- αναγνωριστικό εμπόρου // ID of saler
    ,customer\_id integer  \-\- αναγνωριστικό πελάτη // ID of customer
    ,product\_name dm\_name
\);
    
commit;
set list on;
select id, ddl\_event, object\_name, old\_object\_name, new\_object\_name, sql\_text, ok, result\_info
from ddl\_log order by id;

===

3. Run:

isql -q -i c2724-run.sql 1>c2724-run-ch_none.log 2>&1

4. Result::

ID 2
DDL_EVENT CREATE DOMAIN
OBJECT_NAME DM_NAME
OLD_OBJECT_NAME <null>
NEW_OBJECT_NAME <null>
SQL_TEXT 80:2
create domain dm_name varchar(50) check (value in ('??????????????????', '??????????', '????????????', '??????????????', '????????????????'))
OK Y
RESULT_INFO 80:4
Τα πάντα ήταν επιτυχής

ID 3
DDL_EVENT CREATE TABLE
OBJECT_NAME T1
OLD_OBJECT_NAME <null>
NEW_OBJECT_NAME <null>
SQL_TEXT 80:5
recreate table t1 (
saller_id integer -- ?????????????????????????? ?????????????? // ID of saler
,customer_id integer -- ?????????????????????????? ???????????? // ID of customer
,product_name dm_name
)
OK Y
RESULT_INFO 80:7
Τα πάντα ήταν επιτυχής

So, despite of connection charset = NONE, blob field 'RESULT_INFO' contains readable text in Greek in contrast to comments on table fields and list of avail/ string literals in domain CHECK constraint definition.

@firebird-automations
Copy link
Collaborator Author

Commented by: @asfernandes

'Τα πάντα ήταν επιτυχής' is string in UTF-8, you created it with this connection charset.

The others are NONE strings, and right in the parser, all non-ascii characters are tranformed to question mark.

@firebird-automations
Copy link
Collaborator Author

Modified by: @pavel-zotov

status: Closed [ 6 ] => Closed [ 6 ]

QA Status: No test => Done successfully

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

No branches or pull requests

2 participants