CL_ABAP_DYN_PRG - Support for dynamic programming

ROGBILLS - Synchronize billing plans   Vendor Master (General Section)  
This documentation is copyright by SAP AG.

Functionality

Class CL_ABAP_DYN_PRG offers some static methods that should be used to produce correct and secure code for dynamic programming.

Here are some recommendations how to use these methods in the context of OPEN SQL statements with dynamic parts:

Handling of literal values in conditions

Suppose you are constructing a condition for a dynamic WHERE or HAVING clause and there are values thatcome from some external source and that are used as literals in conditions. Suppose such a value is in ABAP variable lv_val. A typical way of constructing a condition is:

CONCATENATE 'COL1 = ''' lv_val '''' INTO lv_cond.

What if there is a single quote in lv_val, e. g. O'Hara? The condition in lv_cond would contain a syntax error, it would look like this:

COL1 = 'O'Hara'

Or an attacker might be able to put the following value into lv_val:

ABC' OR LANGU <> 'X

This would result in the following condition in lv_cond:

COL1 = 'ABC' OR LANGU <> 'X'

This is probably not what you want. The single quotes must be escaped (i. e. replaced by two subsequent quotes) in order to get correct and secure coding. Use method cl_abap_dyn_prg=>escape_quotes( ):

DATA: lv_temp TYPE string.
lv_temp = cl_abap_dyn_prg=>escape_quotes( lv_val ).
CONCATENATE 'COL1 = ''' lv_temp '''' INTO lv_cond.

Attention: Do not call cl_abap_dyn_prg=>escape_quotes( ) if the quotes have already been escaped.

You can also have the enclosing quotes added automatically using method cl_abap_dyn_prg=>quote( ). Notethat a literal string (with backquotes) is used in this example in order to preserve the blank between the "=" and the quoted value:

DATA: lv_temp TYPE string.
lv_temp = cl_abap_dyn_prg=>quote( lv_val ).
CONCATENATE `COL1 = ` lv_temp INTO lv_cond.

If you use backquotes rather than single quotes in your condition then use methods cl_abap_dyn_prg=>escape_quotes_str( ) or cl_abap_dyn_prg=>quote_str( ):

DATA: lv_temp TYPE string.
lv_temp = cl_abap_dyn_prg=>escape_quotes_str( lv_val ).
CONCATENATE 'COL1 = `' lv_temp '`' INTO lv_cond.

Or

DATA: lv_temp TYPE string.
lv_temp = cl_abap_dyn_prg=>quote_str( lv_val ).
CONCATENATE `COL1 = ` lv_temp INTO lv_cond.

If lv_val should contain an integer value in character representation then you should make sure thatthis is really true by calling method cl_abap_dyn_prg=>check_int_value( ). Here again, make sure that the blanks are handled correctly:

TRY.
    cl_abap_dyn_prg=>check_int_value( lv_val ).
  CATCH cx_abap_not_an_integer.
    RETURN. " In reality do some meaningful error handling here.
ENDTRY.
CONCATENATE `COL1 = ` lv_val INTO lv_cond.

Handling of column and variable names

Suppose you are constructing an OPEN SQL statement in which column names or variable names are determinedat runtime. If you can't make sure that the sources of the names are trustworthy and secure then you should make sure that they are okay by calling one of the following methods:

  • cl_abap_dyn_prg=>check_column_name( ): This method makes sure that there are no malicious characters in a column name that might result in an unwanted SQL statement.
  • cl_abap_dyn_prg=>check_variable_name( ): This is essentially the same as cl_abap_dyn_prg=>check_column_name( ), but use it for the names of ABAP variables. In the future the two methods might become different.
  • cl_abap_dyn_prg=>check_whitelist_tab( ): This method checks whether a given value (e. g. a column name) is in a set of allowed values (whitelist). For this method the whitelist is passed as an internal table.
  • cl_abap_dyn_prg=>check_whitelist_str( ): This is essentially the same as cl_abap_dyn_prg=>check_whitelist_tab( ), except that the whitelist is given as a comma-separated list in a string.

Examples:

We expect that there is a valid column name in lv_val. We are just checking that there are no malicious characters in lv_val:

TRY.
    cl_abap_dyn_prg=>check_column_name( lv_val ).
  CATCH cx_abap_invalid_name.
    RETURN. " In reality do some meaningful error handling here.
ENDTRY.
CONCATENATE lv_val ' <= ''N''' INTO lv_cond.

In the next example we are checking that lv_var contains a non-malicious ABAP variable name:

TRY.
    cl_abap_dyn_prg=>check_variable_name( lv_val ).
  CATCH cx_abap_invalid_name.
    RETURN. " In reality do some meaningful error handling here.
ENDTRY.
CONCATENATE 'COL1 <= ' lv_val INTO lv_cond SEPARATED BY SPACE.

In case you know a limited number of allowed columns you can use method cl_abap_dyn_prg=>check_whitelist_tab( ):

DATA: whitelist TYPE string_hashed_table.
TRY.
    INSERT `COLUMN1` INTO TABLE whitelist.
    INSERT `COLUMNX` INTO TABLE whitelist.
    INSERT `COLUMN9` INTO TABLE whitelist.
    cl_abap_dyn_prg=>check_whitelist_tab( val       = lv_val
                                         whitelist = whitelist ).
  CATCH cx_abap_not_in_whitelist.
    RETURN. " In reality do some meaningful error handling here.
ENDTRY.
CONCATENATE lv_val ' <= ''N''' INTO lv_cond.

If you find it too troublesome to maintain a string_hashed_table for this purpose you can also use acomma-separated list in a string to accomplish the same, but note that this costs some runtime. Use method cl_abap_dyn_prg=>check_whitelist_str( ):

TRY.
    cl_abap_dyn_prg=>check_whitelist_str( val       = lv_val
                                         whitelist = `COLUMN1, COLUMNX, COLUMN9` ).
  CATCH cx_abap_not_in_whitelist.
    RETURN. " In reality do some meaningful error handling here.
ENDTRY.
CONCATENATE lv_val ' <= ''N''' INTO lv_cond.

Handling of table names

Suppose you must construct an OPEN SQL statement with a dynamic table name and that table name is inyour variable lv_val. If you can't make sure whether the table name originates from a trustworthy source,you can use method cl_abap_dyn_prg=>check_table_name_tab( ) to make sure that lv_val really containsthe name of a database table and that this table is in a certain package or a certain set of packages (optionally including its/their subpackages). Example:

DATA: packages TYPE string_hashed_table.
TRY.
    INSERT `SACC` INTO TABLE packages.
    INSERT `SABP` INTO TABLE packages.
    cl_abap_dyn_prg=>check_table_name_tab( val      = lv_val
                                          packages = packages ).
  CATCH cx_abap_not_a_table
        cx_abap_not_in_package.
    RETURN. " In reality do some meaningful error handling here.
ENDTRY.

Similar to the whitelist methods you can also specify the allowed package(s) as a string with a comma-separated list using method cl_abap_dyn_prg=>check_table_name_str( ):

TRY.
    cl_abap_dyn_prg=>check_table_name_str( val      = lv_val
                                          packages = `SACC,SABP` ).
  CATCH cx_abap_not_a_table
        cx_abap_not_in_package.
    RETURN. " In reality do some meaningful error handling here.
ENDTRY.

Of course, you can also use methods cl_abap_dyn_prg=>check_whitelist_tab( ) or cl_abap_dyn_prg=>check_whitelist_str( ) if you want to limit the possible tables to a well-knows set of tables.

Relationships

Example

Notes

Further information



rdisp/max_wprun_time - Maximum work process run time   PERFORM Short Reference  
This documentation is copyright by SAP AG.


Length: 9584 Date: 20120526 Time: 081120     triton ( 193 ms )