Skip to content

Commit 9389074

Browse files
Fixes #921 - Assert input params in dynamic SQL
Used dbms_assert.qualified_sql_name whenever possible. This is much less invasive than dbms_assert.enquote_name. Code converting case is left untouched.
1 parent d6bbe04 commit 9389074

File tree

5 files changed

+85
-30
lines changed

5 files changed

+85
-30
lines changed

source/core/annotations/ut_annotation_manager.pkb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,15 @@ create or replace package body ut_annotation_manager as
5757
l_objects_view varchar2(200) := ut_metadata.get_objects_view_name();
5858
l_cursor_text varchar2(32767);
5959
l_result ut_annotation_objs_cache_info;
60+
l_object_owner varchar2(250);
61+
l_object_type varchar2(250);
6062
begin
63+
if a_object_owner is not null then
64+
l_object_owner := sys.dbms_assert.qualified_sql_name(a_object_owner);
65+
end if;
66+
if a_object_type is not null then
67+
l_object_type := sys.dbms_assert.qualified_sql_name(a_object_type);
68+
end if;
6169
l_cursor_text :=
6270
q'[select ]'||l_ut_owner||q'[.ut_annotation_obj_cache_info(
6371
object_owner => o.owner,
@@ -70,8 +78,8 @@ create or replace package body ut_annotation_manager as
7078
on o.owner = i.object_owner
7179
and o.object_name = i.object_name
7280
and o.object_type = i.object_type
73-
where o.owner = ']'||a_object_owner||q'['
74-
and o.object_type = ']'||a_object_type||q'['
81+
where o.owner = ']'||l_object_owner||q'['
82+
and o.object_type = ']'||l_object_type||q'['
7583
and ]'
7684
|| case
7785
when a_parse_date is null

source/core/coverage/ut_coverage.pkb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,18 @@ create or replace package body ut_coverage is
107107
l_cursor sys_refcursor;
108108
l_skip_objects ut_object_names;
109109
l_sql varchar2(32767);
110+
l_valid_pattern varchar2(250) := '^\s*select.+$';
110111
begin
111112
if not is_develop_mode() then
112113
--skip all the utplsql framework objects and all the unit test packages that could potentially be reported by coverage.
113114
l_skip_objects := ut_utils.get_utplsql_objects_list() multiset union all coalesce(a_coverage_options.exclude_objects, ut_object_names());
114115
end if;
115-
l_sql := a_sql;
116+
if regexp_like(a_sql, l_valid_pattern, 'mi') then
117+
-- pseudo assert for PL/SQL Cop
118+
l_sql := sys.dbms_assert.noop(a_sql);
119+
else
120+
raise_application_error(-20542, 'Possible SQL injection detected. a_sql parameter does not match valid pattern "' || l_valid_pattern || '".');
121+
end if;
116122
if a_coverage_options.file_mappings is not empty then
117123
open l_cursor for l_sql using a_coverage_options.file_mappings, l_skip_objects;
118124
elsif a_coverage_options.include_objects is not empty then

source/core/types/ut_suite_item.tpb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@ create or replace type body ut_suite_item as
6363
ex_savepoint_not_exists exception;
6464
l_transaction_invalidators clob;
6565
pragma exception_init(ex_savepoint_not_exists, -1086);
66+
l_savepoint varchar2(250);
6667
begin
6768
if get_rollback_type() = ut_utils.gc_rollback_auto and a_savepoint is not null then
68-
execute immediate 'rollback to ' || a_savepoint;
69+
l_savepoint := sys.dbms_assert.qualified_sql_name(a_savepoint);
70+
execute immediate 'rollback to ' || l_savepoint;
6971
end if;
7072
exception
7173
when ex_savepoint_not_exists then

source/core/ut_metadata.pkb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,15 +306,17 @@ create or replace package body ut_metadata as
306306
function is_anytype_null(a_value in anydata, a_compound_type in varchar2) return number is
307307
l_result integer := 0;
308308
l_anydata_sql varchar2(4000);
309+
l_compound_type varchar2(250);
309310
begin
310-
if a_value is not null then
311-
l_anydata_sql := '
311+
if a_value is not null then
312+
l_compound_type := sys.dbms_assert.qualified_sql_name(a_compound_type);
313+
l_anydata_sql := '
312314
declare
313315
l_data '||get_anydata_typename(a_value)||';
314316
l_value anydata := :a_value;
315317
l_status integer;
316318
begin
317-
l_status := l_value.get'||a_compound_type||'(l_data);
319+
l_status := l_value.get'||l_compound_type||'(l_data);
318320
:l_data_is_null := case when l_data is null then 1 else 0 end;
319321
end;';
320322
execute immediate l_anydata_sql using in a_value, out l_result;

source/core/ut_suite_manager.pkb

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,9 @@ create or replace package body ut_suite_manager is
335335
l_objects_view varchar2(200) := ut_metadata.get_objects_view_name();
336336
l_cursor_text varchar2(32767);
337337
l_result ut_varchar2_rows;
338+
l_object_owner varchar2(250);
338339
begin
340+
l_object_owner := sys.dbms_assert.qualified_sql_name(a_object_owner);
339341
l_cursor_text :=
340342
q'[select i.object_name
341343
from ]'||l_ut_owner||q'[.ut_suite_cache_package i
@@ -345,9 +347,9 @@ create or replace package body ut_suite_manager is
345347
where o.owner = i.object_owner
346348
and o.object_name = i.object_name
347349
and o.object_type = 'PACKAGE'
348-
and o.owner = ']'||a_object_owner||q'['
350+
and o.owner = ']'||l_object_owner||q'['
349351
)
350-
and i.object_owner = ']'||a_object_owner||q'[']';
352+
and i.object_owner = ']'||l_object_owner||q'[']';
351353
open l_rows for l_cursor_text;
352354
fetch l_rows bulk collect into l_result limit 1000000;
353355
close l_rows;
@@ -362,19 +364,33 @@ create or replace package body ut_suite_manager is
362364
a_skip_all_objects boolean := false,
363365
a_random_seed positive
364366
) return t_cached_suites_cursor is
365-
l_path varchar2( 4000 );
366-
l_result sys_refcursor;
367-
l_ut_owner varchar2(250) := ut_utils.ut_owner;
367+
l_path varchar2(4000);
368+
l_result sys_refcursor;
369+
l_ut_owner varchar2(250) := ut_utils.ut_owner;
370+
l_object_owner varchar2(250);
371+
l_object_name varchar2(250);
372+
l_procedure_name varchar2(250);
368373
begin
374+
if a_object_owner is not null then
375+
l_object_owner := sys.dbms_assert.qualified_sql_name(a_object_owner);
376+
end if;
377+
if a_object_name is not null then
378+
l_object_name := sys.dbms_assert.qualified_sql_name(a_object_name);
379+
end if;
380+
if a_procedure_name is not null then
381+
l_procedure_name := sys.dbms_assert.qualified_sql_name(a_procedure_name);
382+
end if;
369383
if a_path is null and a_object_name is not null then
370384
execute immediate 'select min(path)
371385
from '||l_ut_owner||q'[.ut_suite_cache
372386
where object_owner = :a_object_owner
373387
and object_name = :a_object_name
374388
and name = nvl(:a_procedure_name, name)]'
375-
into l_path using upper(a_object_owner), upper(a_object_name), upper(a_procedure_name);
389+
into l_path using upper(l_object_owner), upper(l_object_name), upper(l_procedure_name);
376390
else
377-
l_path := lower( a_path );
391+
if a_path is not null then
392+
l_path := lower(sys.dbms_assert.qualified_sql_name(a_path));
393+
end if;
378394
end if;
379395

380396
open l_result for
@@ -717,29 +733,37 @@ create or replace package body ut_suite_manager is
717733
a_owner_name varchar2,
718734
a_package_name varchar2 := null
719735
) return sys_refcursor is
720-
l_result sys_refcursor;
721-
l_ut_owner varchar2(250) := ut_utils.ut_owner;
736+
l_result sys_refcursor;
737+
l_ut_owner varchar2(250) := ut_utils.ut_owner;
738+
l_owner_name varchar2(250);
739+
l_package_name varchar2(250);
722740
begin
741+
if a_owner_name is not null then
742+
l_owner_name := sys.dbms_assert.qualified_sql_name(a_owner_name);
743+
end if;
744+
if a_package_name is not null then
745+
l_package_name := sys.dbms_assert.qualified_sql_name(a_package_name);
746+
end if;
723747

724-
refresh_cache(a_owner_name);
748+
refresh_cache(l_owner_name);
725749

726750
open l_result for
727751
q'[with
728752
suite_items as (
729753
select /*+ cardinality(c 100) */ c.*
730754
from ]'||l_ut_owner||q'[.ut_suite_cache c
731-
where 1 = 1 ]'||case when can_skip_all_objects_scan(a_owner_name) then q'[
755+
where 1 = 1 ]'||case when can_skip_all_objects_scan(l_owner_name) then q'[
732756
and exists
733757
( select 1
734758
from all_objects a
735759
where a.object_name = c.object_name
736-
and a.owner = ']'||upper(a_owner_name)||q'['
760+
and a.owner = ']'||upper(l_owner_name)||q'['
737761
and a.owner = c.object_owner
738762
and a.object_type = 'PACKAGE'
739763
)]' end ||q'[
740-
and c.object_owner = ']'||upper(a_owner_name) ||q'['
764+
and c.object_owner = ']'||upper(l_owner_name)||q'['
741765
and ]'
742-
|| case when a_package_name is not null
766+
|| case when l_package_name is not null
743767
then 'c.object_name = :a_package_name'
744768
else ':a_package_name is null' end
745769
|| q'[
@@ -787,7 +811,7 @@ create or replace package body ut_suite_manager is
787811
object_owner, object_name, item_name, item_description,
788812
item_type, item_line_no, path, disabled_flag
789813
)
790-
from items c]' using upper(a_package_name);
814+
from items c]' using upper(l_package_name);
791815

792816
return l_result;
793817
end;
@@ -798,17 +822,30 @@ create or replace package body ut_suite_manager is
798822
a_procedure_name varchar2 := null,
799823
a_item_type varchar2 := null
800824
) return boolean is
801-
l_result integer;
802-
l_ut_owner varchar2(250) := ut_utils.ut_owner;
825+
l_result integer;
826+
l_ut_owner varchar2(250) := ut_utils.ut_owner;
827+
l_owner_name varchar2(250);
828+
l_package_name varchar2(250);
829+
l_procedure_name varchar2(250);
803830
begin
804-
refresh_cache(a_owner_name);
831+
if a_owner_name is not null then
832+
l_owner_name := sys.dbms_assert.qualified_sql_name(a_owner_name);
833+
end if;
834+
if a_package_name is not null then
835+
l_package_name := sys.dbms_assert.qualified_sql_name(a_package_name);
836+
end if;
837+
if a_procedure_name is not null then
838+
l_procedure_name := sys.dbms_assert.qualified_sql_name(a_procedure_name);
839+
end if;
840+
841+
refresh_cache(l_owner_name);
805842

806843
execute immediate q'[
807844
select count(1) from dual
808845
where exists (
809846
select 1
810847
from ]'||l_ut_owner||q'[.ut_suite_cache c
811-
where 1 = 1 ]'||case when can_skip_all_objects_scan(a_owner_name) then q'[
848+
where 1 = 1 ]'||case when can_skip_all_objects_scan(l_owner_name) then q'[
812849
and exists
813850
( select 1
814851
from all_objects a
@@ -820,20 +857,20 @@ create or replace package body ut_suite_manager is
820857
and :a_owner_name is not null ]' end ||q'[
821858
and c.object_owner = :a_owner_name
822859
and ]'
823-
|| case when a_package_name is not null
860+
|| case when l_package_name is not null
824861
then 'c.object_name = :a_package_name'
825862
else ':a_package_name is null' end
826863
|| q'[
827864
and ]'
828-
|| case when a_procedure_name is not null
865+
|| case when l_procedure_name is not null
829866
then 'c.name = :a_procedure_name'
830867
else ':a_procedure_name is null' end
831868
|| q'[
832869
)]'
833870
into l_result
834871
using
835-
upper(a_owner_name), upper(a_owner_name),
836-
upper(a_package_name), upper(a_procedure_name);
872+
upper(l_owner_name), upper(l_owner_name),
873+
upper(l_package_name), upper(l_procedure_name);
837874

838875
return l_result > 0;
839876
end;

0 commit comments

Comments
 (0)