Manpages

NAME

perlsec − Perl 安 全

DESCRIPTION 描 述

Perl可 以 輕 鬆 寫 出 安 全 的 程 式 , 即 使 運 行 時 有 特 殊 權 限 , 比 如 setuid或 setgid程 式 。 許 \[u591A]稿 本 的 命 令 行 裏 有 多 項 替 換 語 句 , Perl卻 不 是 這 樣 , 它 使 用 更 多 傳 統 方 法 而 少 有 艱 深 。 而 且 , 由 於 perl語 言 有 更 多 內 在 功 \[u80FD], 它 可 以 更 少 的 依 賴 於 其 他 ( 可 能 不 可 信 的 ) 程 式 來 完 成 根 本 目 的 。

當 Perl檢 測 到 程 式 中 真 實 的 使 用 者 或 組 ID與 有 效 使 用 者 或 組 ID不 同 時 , 它 自 動 地 開 啟 一 種 叫 做 「 污 染 模 式 」 特 殊 的 安 全 性 檢 測 。 setuid的 unix的 權 限 位 是 04000, setgid 的 UNIX權 限 位 是 02000; 它 們 都 有 可 能 被 設 置 。 你 也 可 以 用 命 令 行 標 識 −T 明 確 地 開 啟 「 污 染 模 式 」 。 強 烈 建 議 伺 服 器 程 式 或 者 在 以 其 他 人 身 份 運 行 的 程 式 ( 比 如 CGI稿 本 ) 使 用 此 標 識 符 。 一 旦 污 染 模 式 被 打 開 , 它 在 稿 本 的 餘 下 內 容 中 一 直 開 啟 。

在 「 污 染 模 式 」 中 , Perl使 用 叫 做 「 污 染 檢 測 」 的 特 殊 預 防 方 法 來 防 止 明 顯 的 和 不 易 被 察 覺 的 陷 阱 。 一 些 檢 測 相 當 簡 單 , 如 檢 查 路 徑 目 錄 以 確 定 它 們 對 其 他 人 是 不 可 寫 的 ; 小 心 的 程 式 員 一 向 做 此 類 檢 測 。 其 他 的 檢 測 已 經 得 到 Perl本 身 最 好 的 支 持 , 這 些 檢 測 尤 其 使 寫 一 個 set-id的 Perl程 式 比 相 應 的 C程 式 更 安 全 。

你 不 可 以 使 用 來 自 程 式 之 外 的 數 據 來 影 響 程 式 之 外 的 事 情 ──至 少 不 是 偶 然 的 。 所 有 命 令 行 參 數 , 環 境 變 量 , 本 地 信 息 ( 參 見 perllocale) , 特 定 系 統 調 用 的 結 果 ( readdir(),readlink(),shmread()的 變 量 ,msgrcv()的 返 回 信 息 ,getpwxxx()調 用 返 回 的 密 碼 、 gcos和 shell域 ) 和 所 有 檔 案 輸 入 都 被 標 記 成 「 污 染 的 」 。 「 污 染 的 」 數 據 既 不 可 以 直 接 或 間 接 在 任 何 調 用 一 個 子 shell命 令 中 使 用 , 也 不 能 在 任 何 修 改 檔 案 、 目 錄 或 進 程 的 命 令 中 使 用 , 但 有 以 下 例 外 :

print和 syswrite的 參 數 不 被 檢 查 是 否 被 污 染 。

符 號 方 法

    $obj->$method(@args);

以 及 符 號 的 子 引 用

    &{$foo}(@args);
    $foo->(@args);

不 會 被 檢 查 是 否 被 污 染 。 這 要 求 額 外 的 小 心 , 除 非 你 希 望 外 部 數 據 影 響 你 的 控 制 流 。 除 非 你 小 心 地 限 制 這 些 符 號 值 是 什 麼 , 人 們 可 以 從 Perl 代 碼 外 部 調 用 函 數 , 類 似 POSIX::system, 來 運 行 任 意 外 部 代 碼 。

為 了 效 率 原 因 , Perl 對 數 據 是 否 已 被 污 染 持 保 守 的 看 法 。 如 果 一 個 表 達 式 包 含 污 染 的 數 據 , 任 何 子 表 達 式 都 被 認 為 污 染 的 , 即 使 自 表 達 式 的 值 與 污 染 的 數 據 無 關

由 於 污 染 與 每 個 標 量 值 相 關 , 一 個 數 組 或 散 列 的 元 素 可 以 只 有 一 部 分 被 污 染 。 散 列 的 鍵 永 遠 不 會 被 污 染 。

例 如 :

    $arg = shift;               # $arg 是 污 染 的
    $hid = $arg, ’bar’;         # $hid 也 是 污 染 的
    $line = <>;                 # 污 染 的
    $line = <STDIN>;            # 仍 舊 是 污 染 的
    open FOO, "/home/me/bar" or die $!;
    $line = <FOO>;              # 還 是 污 染 的
    $path = $ENV{’PATH’};       # 污 染 的 , 但 是 請 看 下 面
    $data = ’abc’;              # 非 污 染 的
    system "echo $arg";         # 不 安 全 的
    system "/bin/echo", $arg;   # 認 為 不 安 全
                                # (Perl 不 知 道  /bin/echo)
    system "echo $hid";         # 不 安 全 的
    system "echo $data";        # 如 果 PATH被 設 定 , 那 麼 才 是 安 全 的
    $path = $ENV{’PATH’};       # $path 現 在 是 污 染 的
    $ENV{’PATH’} = ’/bin:/usr/bin’;
    delete @ENV{’IFS’, ’CDPATH’, ’ENV’, ’BASH_ENV’};
    $path = $ENV{’PATH’};       # $path 現 在 不 是 污 染 的
    system "echo $data";        # 現 在 是 安 全 的 !
    open(FOO, "< $arg");        # OK - 只 讀 檔 案
    open(FOO, "> $arg");        # Not OK - 試 圖 去 寫
    open(FOO,"echo $arg⎪");     # Not OK
    open(FOO,"-⎪")
        or exec ’echo’, $arg;   # 同 樣  not OK
    $shout = ’echo $arg’;       # 不 安 全 的 , $shout 現 在 是 污 染 的
    unlink $data, $arg;         # 不 安 全 的
    umask $arg;                 # 不 安 全 的
    exec "echo $arg";           # 不 安 全 的
    exec "echo", $arg;          # 不 安 全 的
    exec "sh", ’-c’, $arg;      # 非 常 不 安 全 !
    @files = <*.c>;             # 不 安 全 的  (使 用  readdir() 或 其 他 )
    @files = glob(’*.c’);       # 不 安 全 的  (使 用  readdir() 或 其 他 )
    # In Perl releases older than 5.6.0 the <*.c> and glob(’*.c’) would
    # have used an external program to do the filename expansion; but in
    # either case the result is tainted since the list of filenames comes
    # from outside of the program.

    $bad = ($arg, 23);          # $bad will be tainted
    $arg, ’true’;               # Insecure (although it isn’t really)

如 果 你 試 圖 做 一 些 不 安 全 的 事 情 , 你 會 得 到 類 似 "Insecure dependency"或 "Insecure $ENV{PATH}"的 致 命 錯 誤 。

Laundering and Detecting Tainted Data 清 洗 和 檢 測 污 染 數 據

測 試 一 個 變 量 是 否 含 有 污 染 的 數 據 , 誰 的 用 法 會 引 發 一 條 "Insecure dependency"信 息 , 在 你 附 近 的 CPAN鏡 像 查 找 Taint.pm模 塊 , 它 應 該 在 1997年 左 右 就 可 以 得 到 。 或 者 你 可 以 用 is_tainted()函 數 。

    sub is_tainted {
        return ! eval { eval("#" . substr(join("", @_), 0, 0)); 1 };
    }

此 函 數 利 用 了 「 表 達 式 中 任 何 一 部 分 存 在 的 污 染 數 據 致 使 整 個 表 達 式 都 被 污 染 」 。 操 作 員 測 試 每 個 參 數 是 否 被 污 染 會 使 效 率 低 下 。 相 反 , 稍 稍 高 效 且 穩 定 的 方 法 是 , 只 要 一 個 表 達 式 中 任 何 一 部 分 存 取 一 個 被 污 染 的 值 , 那 麼 這 個 表 達 式 被 認 為 是 被 污 染 的 。

但 是 僅 僅 測 試 數 據 是 否 被 污 染 還 不 夠 。 有 時 你 必 須 清 除 數 據 的 污 染 。 唯 一 的 通 過 污 染 機 制 的 方 法 是 引 用 正 則 表 達 式 中 的 一 個 子 模 式 。 Perl假 定 如 果 你 用 $1, $2等 等 引 用 一 個 子 串 , 那 麼 你 就 知 道 你 在 做 什 麼 。 也 就 是 說 你 必 須 思 考 而 不 是 盲 目 的 解 除 污 染 , 或 者 違 抗 整 個 機 制 。 校 驗 變 量 是 否 只 含 有 好 的 字 符 ( 已 知 的 好 的 字 符 ) 比 檢 查 它 是 否 含 有 壞 的 字 符 要 好 。 是 因 為 很 可 能 就 把 意 料 之 外 的 壞 字 符 漏 掉 。

下 面 的 例 子 是 一 個 檢 查 數 據 中 是 否 只 含 有 單 詞 ( 字 母 、 數 字 、 下 劃 線 ) 、 連 字 符 、 ’@’符 號 或 者 是 ’.’。

    if ($data =~ /^([-\@\w.]+)$/) {
        $data = $1;                     # $data now untainted
    } else {
        die "Bad data in ’$data’";      # log this somewhere
    }

這 完 全 沒 有 問 題 , 因 為 /1920/從 理 論 上 講 會 不 安 全 , 因 為 它 匹 配 任 何 字 符 , 而 Perl將 不 再 檢 查 它 們 。 我 們 的 經 驗 是 當 你 解 除 污 染 時 , 必 須 對 匹 配 模 式 極 其 的 小 心 。 使 用 正 則 表 達 式 清 洗 數 據 是 解 除 污 染 的 唯 一 機 制 , 除 非 你 使 用 下 面 才 詳 細 敘 述 的 派 生 一 個 特 權 被 降 低 的 字 進 程 的 方 法 。

如 果 程 式 中 使 用 了 use locale, 那 麼 上 面 的 例 子 將 不 會 解 除 $data的 污 染 , 因 為 4920

當 你 使 稿 本 程 式 可 執 行 , 就 是 可 以 像 命 令 一 樣 讓 它 們 工 作 時 , 系 統 會 把 "#!"行 的 開 關 傳 遞 給 Perl。 Perl檢 查 setuid( 或 setgid) 程 式 的 任 何 和 "#!"行 開 關 匹 配 的 命 令 行 開 關 。 一 些 Unix或 Unix-like系 統 環 境 強 制 在 "#!"行 使 用 一 個 開 關 , 所 以 你 也 許 \[u5FC5]須 用 類 似 -wU的 開 關 而 不 是 -w -U。 ( 這 個 問 題 只 出 現 在 支 持 #!、 setuid、 setgid稿 本 的 Unix或 Unix-like系 統 環 境 中 )

Taint mode and @INC

When the taint mode ("−T") is in effect, the "." directory is removed from @INC, and the environment variables "PERL5LIB" and "PERLLIB" are ignored by Perl. You can still adjust @INC from outside the program by using the "−I" command line option as explained in perlrun. The two environment variables are ignored because they are obscured, and a user running a program could be unaware that they are set, whereas the "−I" option is clearly visible and therefore permitted.

Another way to modify @INC without modifying the program, is to use the "lib" pragma, e.g.:

  perl -Mlib=/foo program

The benefit of using "−Mlib=/foo" over "−I/foo", is that the former will automagically remove any duplicated directories, while the later will not.

Cleaning Up Your Path 清 理 路 徑

對 於 "Insecure $ENV{PATH}"這 樣 的 信 息 , 你 必 須 把 $ENV{PATH}設 置 為 已 知 的 , 並 且 路 徑 中 的 任 何 目 錄 都 對 於 非 本 使 用 者 或 非 本 組 成 員 不 可 寫 。 你 也 許 \[u6703]在 即 使 路 徑 名 是 完 全 合 法 的 情 況 下 收 到 那 條 信 息 表 示 非 常 驚 訝 。 當 你 沒 有 提 供 程 式 一 個 完 整 的 路 徑 時 , 它 不 會 被 引 起 ; 相 反 , 若 你 從 未 設 置 PATH環 境 變 量 , 或 者 你 沒 有 把 它 設 置 安 全 , 它 就 會 被 引 起 。 因 為 Perl不 能 保 証 可 疑 的 可 執 行 程 式 是 不 是 它 本 身 將 執 行 其 他 的 依 賴 於 PATH的 程 式 , 它 確 定 是 你 設 定 的 PATH。

PATH不 是 唯 一 可 能 導 致 問 題 的 變 量 。 因 為 一 些 shell會 使 用 IFS, CDPATH, ENV和 BASH_ENV, Perl在 開 始 子 進 程 時 檢 查 它 們 是 否 也 為 空 或 者 未 污 染 。 你 也 許 \[u6703]在 你 的 set-id和 污 染 檢 測 模 式 下 的 稿 本 程 式 中 加 入 這 些 東 西 :

    delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};   # 使  %ENV 更 安 全

當 然 , 無 論 是 否 使 用 污 染 變 量 都 有 可 能 出 現 麻 煩 。 在 處 理 任 何 由 使 用 者 提 供 的 檔 名 的 檔 案 時 , 要 做 周 密 的 測 試 。 必 須 時 , 可 以 在 去 掉 使 用 者 ( 或 組 ! ) 的 特 權 之 後 再 進 行 類 似 open的 操 作 。 Perl不 阻 止 你 打 開 污 染 的 檔 名 並 讀 取 內 容 , 所 以 要 小 心 對 待 列 印 出 的 內 容 。 污 染 機 制 的 目 的 是 防 止 愚 蠢 的 錯 誤 , 不 是 使 人 懶 惰 不 去 思 考 。

當 你 傳 遞 給 system和 exec明 確 的 參 數 列 表 而 非 含 有 通 配 符 的 字 符 串 時 , Perl不 會 調 用 shell去 擴 展 通 配 符 。 不 幸 的 是 , open, glob, backtick( 譯 注 : backtick為 反 引 號 ) 函 數 並 不 提 供 這 樣 的 特 性 , 所 以 當 使 用 它 們 的 時 候 必 須 非 常 仔 細 。

Perl為 從 一 個 setuid或 setgid程 式 打 開 檔 案 或 管 道 提 供 了 一 個 安 全 的 方 法 : 創 建 一 個 減 少 權 限 的 子 進 程 來 為 你 完 成 那 些 「 骯 臟 」 的 工 作 。 首 先 , 用 特 殊 的 OPEN語 法 創 建 一 個 子 進 程 , 使 其 和 父 進 程 通 過 一 個 管 道 相 連 。 現 在 子 進 程 把 它 的 ID和 其 他 諸 如 環 境 變 量 , umask, 當 前 工 作 目 錄 的 性 質 重 新 設 置 回 原 始 的 或 安 全 的 變 量 。 然 後 讓 該 不 具 有 任 何 特 權 的 子 進 程 來 完 成 OPEN和 其 他 的 系 統 調 用 。 最 終 , 子 進 程 把 它 成 功 \[u5B58]取 的 數 據 傳 遞 給 父 進 程 。 因 為 檔 案 或 管 道 是 由 運 行 於 比 父 進 程 權 限 低 的 子 進 程 打 開 的 , 所 以 它 不 容 易 被 欺 騙 去 做 它 不 該 做 的 事 情 。

這 裏 有 一 個 安 全 使 用 backtick的 方 法 。 注 意 當 shell可 能 擴 展 時 , exec是 如 何 不 被 調 用 的 。 這 是 目 前 來 調 用 可 能 被 shell轉 義 的 東 西 最 好 的 方 法 : 從 不 調 用 shell。

        use English ’-no_match_vars’;
        die "Can’t fork: $!" unless defined($pid = open(KID, "-⎪"));
        if ($pid) {           # parent
            while (<KID>) {
                # do something
            }
            close KID;
        } else {
            my @temp     = ($EUID, $EGID);
            my $orig_uid = $UID;
            my $orig_gid = $GID;
            $EUID = $UID;
            $EGID = $GID;
            # Drop privileges
            $UID  = $orig_uid;
            $GID  = $orig_gid;
            # Make sure privs are really gone
            ($EUID, $EGID) = @temp;
            die "Can’t drop privileges"
                unless $UID == $EUID  && $GID eq $EGID;
            $ENV{PATH} = "/bin:/usr/bin"; # Minimal PATH.
            # Consider sanitizing the environment even more.
            exec ’myprog’, ’arg1’, ’arg2’
                or die "can’t exec myprog: $!";
        }

使 用 類 似 的 策 略 可 以 讓 glob使 用 通 配 符 擴 展 , 雖 然 也 可 以 用 readdir。

當 你 雖 然 相 信 自 己 並 沒 有 寫 有 問 題 的 程 式 , 但 並 不 信 任 程 式 的 最 終 使 用 者 不 會 企 圖 讓 它 做 壞 事 時 , 污 染 檢 測 最 為 有 用 。 此 類 安 全 檢 查 對 set-id和 以 其 他 使 用 者 身 份 運 行 的 程 式 ( 如 CGI) 非 常 有 用 。

若 連 程 式 的 作 者 都 不 可 信 的 話 , 情 況 就 不 同 了 。 當 某 人 給 你 一 段 程 式 並 和 你 說 , 「 給 , 試 試 看 。 」 對 於 此 類 安 全 問 題 , 使 用 包 含 在 Perl發 行 版 中 的 Safe模 塊 。 這 個 模 塊 允 許 \[u7A0B]式 員 建 立 特 殊 的 隔 間 , 在 其 中 所 有 的 系 統 調 用 都 被 截 獲 , 並 且 名 字 空 間 入 口 被 嚴 格 控 制 。

Security Bugs 安 全 問 題

除 了 源 於 賦 予 像 稿 本 一 樣 靈 活 的 系 統 特 權 這 類 明 顯 的 問 題 , 在 許 \[u591A]Unix版 本 中 , set-id稿 本 從 一 開 始 就 是 天 生 不 安 全 的 。 問 題 出 在 核 心 的 條 件 競 爭 。 在 核 心 打 開 檔 案 來 查 看 應 該 運 行 哪 個 解 釋 器 和 當 ( 現 在 已 set-id) 解 釋 器 回 過 頭 來 重 新 打 開 檔 案 並 解 釋 它 的 這 兩 個 事 件 之 間 , 可 疑 的 檔 案 也 許 \[u5DF2]經 改 變 了 , 特 別 是 當 系 統 中 有 符 號 連 接 時 。

幸 運 的 是 , 這 個 核 心 的 「 特 性 」 有 時 可 以 被 關 閉 。 不 幸 的 是 , 有 兩 個 方 法 來 關 閉 它 。 系 統 可 以 簡 單 的 宣 布 任 何 含 有 set-id位 的 稿 本 都 是 不 合 法 的 , 這 個 顯 然 用 處 不 大 。 另 一 個 是 忽 略 稿 本 中 的 set-id位 。 如 果 後 者 被 設 置 為 真 , 那 麼 當 Perl注 意 到 其 它 稿 本 中 無 效 的 setuid/gid位 時 ,它 可 以 模 仿 setuid和 setgid的 機 制 。 這 是 通 過 一 個 叫 做 suidperl的 特 殊 程 式 來 實 現 的 , 它 在 需 要 時 自 動 被 調 用 。

但 是 , 如 果 核 心 的 set-id稿 本 特 性 沒 有 被 關 閉 , Perl就 會 大 聲 抱 怨 你 的 set-id程 式 是 不 安 全 的 。 你 要 麼 需 要 關 閉 核 心 的 set-id稿 本 特 性 , 要 麼 為 稿 本 製 作 一 個 C Wrapper。 一 個 C Wrapper就 是 一 個 除 了 調 用 你 的 Perl程 式 其 他 什 麼 都 不 幹 的 已 編 譯 程 式 。 已 編 譯 程 式 不 受 此 核 心 問 題 的 影 響 去 找 set-id稿 本 的 麻 煩 。 這 裏 有 一 個 簡 單 的 C Wrapper:

    #define REAL_PATH "/path/to/script"
    main(ac, av)
        char **av;
    {
        execv(REAL_PATH, av);
    }

把 此 C Wrapper編 譯 成 可 執 行 二 進 制 檔 案 , 對 它 setuid或 setgid而 不 是 你 的 稿 本 。

近 幾 年 , 軟 體 商 開 始 提 供 沒 有 此 安 全 問 題 的 系 統 。 在 它 們 中 , 當 核 心 把 將 要 被 打 開 的 set-id稿 本 的 名 字 傳 遞 給 解 釋 器 時 , 它 將 不 會 傳 遞 可 能 出 現 問 題 的 路 徑 名 而 是 傳 遞 /dev/fd/3。 這 是 一 個 已 經 在 稿 本 上 打 開 的 特 殊 檔 案 , 所 以 將 不 會 出 現 條 件 競 爭 問 題 。 在 這 些 系 統 中 , Perl需 要 在 編 譯 時 帶 上 -DSETUID_SCRIPTS_ARE_SECURE_NOW參 數 。 Configure程 式 將 自 己 完 成 這 個 任 務 , 所 以 你 永 遠 不 必 要 自 己 指 出 此 點 。 現 在 SVR4和 BSD4.4都 採 用 此 種 方 法 來 避 免 核 心 條 件 競 爭 。

在 Perl 5.6.1 發 行 之 前 , suidperl的 代 碼 問 題 可 能 導 致 安 全 漏 洞 。

Protecting Your Programs 保 護 你 的 程 式

有 很 多 種 方 法 可 以 隱 藏 你 的 Perl程 式 原 始 碼 , 它 們 具 有 不 同 等 級 的 「 安 全 性 」 。

首 先 , 你 不 能 去 掉 「 讀 」 權 限 , 因 為 原 始 碼 必 須 在 被 讀 取 之 後 才 能 編 譯 和 解 釋 。 ( 這 並 不 意 味 著 CGI稿 本 的 原 始 碼 在 網 上 是 可 被 讀 取 的 ) 所 以 你 必 須 把 權 限 設 置 為 對 外 界 友 好 的 0755。 這 使 在 你 本 地 系 統 上 的 人 只 能 查 看 原 始 碼 。

一 些 人 錯 誤 的 認 為 這 是 一 個 安 全 問 題 。 如 果 你 的 程 式 不 安 全 , 而 你 依 賴 人 們 不 知 道 如 何 利 用 這 些 漏 洞 , 這 是 不 安 全 的 。 通 常 某 些 人 在 沒 有 看 原 始 碼 的 情 況 下 就 可 以 利 用 這 些 漏 洞 。 以 隱 藏 來 實 現 所 謂 的 「 安 全 」 而 不 是 修 復 漏 洞 , 是 非 常 不 安 全 的 。

你 可 以 試 著 通 過 原 始 碼 過 濾 器 ( CPAN上 的 Filter::*) 來 實 現 加 密 。 但 是 駭 客 有 可 能 把 它 解 密 。 你 可 以 試 著 使 用 下 面 描 述 的 字 節 碼 編 譯 器 和 解 釋 器 , 但 是 駭 客 有 可 能 把 它 反 編 譯 。 這 些 對 想 看 你 代 碼 的 人 造 成 不 同 難 度 的 困 難 。 但 是 沒 有 一 種 可 以 完 全 的 避 免 ( 不 光 是 Perl, 所 有 語 言 都 一 樣 ) 。

如 果 你 擔 心 有 人 會 通 過 你 的 程 式 得 利 , 那 麼 你 可 以 在 最 低 行 寫 一 個 限 制 性 的 許 \[u53EF]証 來 尋 求 法 律 保 護 。 當 然 如 果 你 用 類 似 「 這 是 某 某 公 司 的 私 人 程 式 , 你 無 權 使 用 它 」 的 聲 明 來 授 權 你 的 軟 體 並 發 佈 它 的 話 , 那 會 是 非 常 危 險 的 。 你 應 該 找 一 個 律 師 確 定 你 的 許 \[u53EF]証 的 措 辭 可 以 在 法 庭 上 站 得 住 腳 。

Unicode

Unicode is a new and complex technology and one may easily overlook certain security pitfalls. See perluniintro for an overview and perlunicode for details, and "Security Implications of Unicode" in perlunicode for security implications in particular.

Algorithmic Complexity Attacks

Certain internal algorithms used in the implementation of Perl can be attacked by choosing the input carefully to consume large amounts of either time or space or both. This can lead into the so-called Denial of Service (DoS) attacks.

Hash Function − the algorithm used to "order" hash elements has been changed several times during the development of Perl, mainly to be reasonably fast. In Perl 5.8.1 also the security aspect was taken into account.

In Perls before 5.8.1 one could rather easily generate data that as hash keys would cause Perl to consume large amounts of time because internal structure of hashes would badly degenerate. In Perl 5.8.1 the hash function is randomly perturbed by a pseudorandom seed which makes generating such naughty hash keys harder. See " PERL_HASH_SEED " in perlrun for more information.

The random perturbation is done by default but if one wants for some reason emulate the old behaviour one can set the environment variable PERL_HASH_SEED to zero (or any other integer). One possible reason for wanting to emulate the old behaviour is that in the new behaviour consecutive runs of Perl will order hash keys differently, which may confuse some applications (like Data::Dumper: the outputs of two different runs are no more identical).

Perl has never guaranteed any ordering of the hash keys, and the ordering has already changed several times during the lifetime of Perl 5. Also, the ordering of hash keys has always been, and continues to be, affected by the insertion order.

Also note that while the order of the hash elements might be randomised, this "pseudoordering" should not be used for applications like shuffling a list randomly (use List::Util::shuffle() for that, see List::Util, a standard core module since Perl 5.8.0; or the CPAN module Algorithm::Numerical::Shuffle), or for generating permutations (use e.g. the CPAN modules Algorithm::Permute or Algorithm::FastPermute), or for any cryptographic applications.

Regular expressions − Perl’s regular expression engine is so called NFA (Non−Finite Automaton), which among other things means that it can rather easily consume large amounts of both time and space if the regular expression may match in several ways. Careful crafting of the regular expressions can help but quite often there really isn’t much one can do (the book "Mastering Regular Expressions" is required reading, see perlfaq2). Running out of space manifests itself by Perl running out of memory.

Sorting − the quicksort algorithm used in Perls before 5.8.0 to implement the sort() function is very easy to trick into misbehaving so that it consumes a lot of time. Nothing more is required than resorting a list already sorted. Starting from Perl 5.8.0 a different sorting algorithm, mergesort, is used. Mergesort is insensitive to its input data, so it cannot be similarly fooled.

See <http://www.cs.rice.edu/~scrosby/hash/>; for more information, and any computer science text book on the algorithmic complexity.

SEE ALSO 參 見

perlrun中 關 於 清 理 環 境 變 量 的 描 述

中 文 版 維 護 人

nan1nan1 <nan1nan1 [AT] hotmail.com>

中 文 版 最 新 更 新

2001年 12月 23日 星 期 日

中 文 手 冊 頁 翻 譯 計 劃

http://cmpp.linuxforum.net