• PostgreSQL quote ident and literal


    PostgreSQL quote ident and literal  

    2013-05-21 16:08:58|  分类: PgSQL Develop |  标签: |字号 订阅

     
     
    前面一篇介绍了SQL注入, 其中利用字符逃逸漏洞的占了主要部分.
     
    PostgreSQL 提供了几个函数用来输出转义后的字符串.
    quote_ident(string text) text Return the given string suitably quoted to be used as an identifier in an SQL statement string. Quotes are added only if necessary (i.e., if the string contains non-identifier characters or would be case-folded). Embedded quotes are properly doubled. See also Example 40-1. quote_ident('Foo bar') "Foo bar"
    quote_literal(string text) text Return the given string suitably quoted to be used as a string literal in an SQL statement string. Embedded single-quotes and backslashes are properly doubled. Note that quote_literal returns null on null input; if the argument might be null, quote_nullable is often more suitable. See also Example 40-1. quote_literal(E'O\'Reilly') 'O''Reilly'
    quote_literal(valueanyelement) text Coerce the given value to text and then quote it as a literal. Embedded single-quotes and backslashes are properly doubled. quote_literal(42.5) '42.5'
    quote_nullable(string text) text Return the given string suitably quoted to be used as a string literal in an SQL statement string; or, if the argument is null, return NULL. Embedded single-quotes and backslashes are properly doubled. See also Example 40-1. quote_nullable(NULL) NULL
    quote_nullable(valueanyelement) text Coerce the given value to text and then quote it as a literal; or, if the argument is null, return NULL. Embedded single-quotes and backslashes are properly doubled. quote_nullable(42.5) '42.5'
    一般可用于构造SQL语句, 例如dblink中的动态SQL语句的构造 : 
    防止因为输入问题造成的不正确SQL.
    quote_ident用于构造数据库对象名, 例如表名, 列名.
    quote_literal用于构造字符串.
    quote_nullable和quote_literal类似, 只是空参数的处理不一样.
    quote_literal是strict的, 输入空, 返回空.
    quote_nullable是not strict的, 内部处理空值, 返回NULL字符串.
    digoal=# select proisstrict,provolatile,proname from pg_proc where proname ~ 'quote';
     proisstrict | provolatile |    proname     
    -------------+-------------+----------------
     t           | i           | quote_ident
     t           | i           | quote_literal
     t           | s           | quote_literal
     f           | i           | quote_nullable
     f           | s           | quote_nullable
    (5 rows)
    src/backend/utils/adt/quote.c
    /*
     * quote_nullable -
     *        Returns a properly quoted literal, with null values returned
     *        as the text string 'NULL'.
     */
    Datum
    quote_nullable(PG_FUNCTION_ARGS)
    {
            if(PG_ARGISNULL(0))
                    PG_RETURN_TEXT_P(cstring_to_text("NULL"));
            else
                    PG_RETURN_DATUM(DirectFunctionCall1(quote_literal,
                                                                                            PG_GETARG_DATUM(0)));
    }
    quote_nullable和quote_literal的差异 : 
    digoal=# select 1 where quote_nullable(null) is null;
     ?column? 
    ----------
    (0 rows)
     
    digoal=# select 1 where quote_literal(null) is null;
     ?column? 
    ----------
            1
    (1 row)
     
    digoal=# select 1 where quote_literal(null)='NULL';
     ?column? 
    ----------
    (0 rows)
     
    digoal=# select 1 where quote_nullable(null)='NULL';
     ?column? 
    ----------
            1
    (1 row)
     
     
    构造动态SQL举例.
    不使用quote : 
    digoal=# create or replace function f_test(i_tablename text, i_cname text, i_cval text) returns void as $$
    declare 
      v_sql text;
    begin
      v_sql := 'create table '||i_tablename||'('||i_cname||' text)';
      raise notice '%', v_sql;
      execute v_sql;
      v_sql := 'insert into '||i_tablename||'('||i_cname||') values ('||i_cval||')';
      raise notice '%', v_sql;
      execute v_sql;
    end;
    $$ language plpgsql;
    CREATE FUNCTION
    # 当表名, 列名中有空格或其他特殊字符时, 必须要用双引号, 因此以下调用将报错.
    digoal=# select f_test('a b','d e','''');
    NOTICE:  00000: create table a b(d e text)
    LOCATION:  exec_stmt_raise, pl_exec.c:2985
    ERROR:  42601: syntax error at or near "b"
    LINE 1: create table a b(d e text)
                           ^
    QUERY:  create table a b(d e text)
    CONTEXT:  PL/pgSQL function f_test(text,text,text) line 7 at EXECUTE statement
    LOCATION:  scanner_yyerror, scan.l:1044
    # 当字符串中使用单引号时, 也必须逃逸, 使用双单引号. 这里也会报错.
    digoal=# select f_test('ab','de','''');
    NOTICE:  00000: create table ab(de text)
    LOCATION:  exec_stmt_raise, pl_exec.c:2985
    NOTICE:  00000: insert into ab(de) values (')
    LOCATION:  exec_stmt_raise, pl_exec.c:2985
    ERROR:  42601: unterminated quoted string at or near "')"
    LINE 1: insert into ab(de) values (')
                                       ^
    QUERY:  insert into ab(de) values (')
    CONTEXT:  PL/pgSQL function f_test(text,text,text) line 10 at EXECUTE statement
    LOCATION:  scanner_yyerror, scan.l:1044
     
    使用quote : 
    使用quote函数后, 数据库会自动根据需要帮你加上双引号和其他逃逸.
    digoal=# create or replace function f_quote(i_tablename text, i_cname text, i_cval text) returns void as $$
    declare 
      v_sql text;
    begin
      v_sql := 'create table '||quote_ident(i_tablename)||'('||quote_ident(i_cname)||' text)';
      raise notice '%', v_sql;
      execute v_sql;
      v_sql := 'insert into '||quote_ident(i_tablename)||'('||quote_ident(i_cname)||') values ('||quote_literal(i_cval)||')';
      raise notice '%', v_sql;
      execute v_sql;
    end;
    $$ language plpgsql;
     
    digoal=# select f_quote('a b','d e','''');
    NOTICE:  00000: create table "a b"("d e" text)
    LOCATION:  exec_stmt_raise, pl_exec.c:2985
    NOTICE:  00000: insert into "a b"("d e") values ('''')
    LOCATION:  exec_stmt_raise, pl_exec.c:2985
     f_quote 
    ---------
     
    (1 row)
     
    digoal=# select * from "a b";
     d e 
    -----
     '
    (1 row)
  • 相关阅读:
    单一index.php实现PHP任意层级文件夹遍历(原创自Zjmainstay)
    php读取文件内容至字符串中,同时去除换行、空行、行首行尾空格(原创自Zjmainstay)
    php获取页面并切割页面div内容
    jQuery单击双击实现链接的提取、插入与删除
    PHP 利用AJAX获取网页并输出(原创自Zjmainstay)
    php 数组首字符过滤功能
    点击图片添加文件在Chrome中使用的兼容问题
    php读取txt文件组成SQL并插入数据库(原创自Zjmainstay)
    为博客园添加标签云动画
    jQuery动态增删改查表格信息,可左键/右键提示(原创自Zjmainstay)
  • 原文地址:https://www.cnblogs.com/xiongsd/p/3118701.html
Copyright © 2020-2023  润新知