使用 `eval` 来定义带有来自文件的文本的函数是邪恶的吗?

Is using `eval` to define functions with text from a file evil?

这是 的后续问题。


我正在使用 eval 来模仿其他语言(例如 JavaScript)的 import 功能。这是我想在我的本地机器上做一段时间的事情,因为我已经建立了一个压倒性的脚本文件集合。

原因是我现在在单独的文件中有大量单独的函数,我不想每次想调用函数时都用 source 不断地读取文件.

这主要是为了好玩,但如果我在不那么随意的情况下使用它,我不想大意:

import_as() { 
  import_name=""
  import_fnname="${2:-"$import_name"}"

  if test -f ""; then
    echo "File '' doesn't exist."
  fi

  case "" in 
    *[!-a-zA-Z0-9_]* ) echo "BAD";; 
    *) eval ""'() { '"$(< .sh)"'; }' ;; 
  esac
}

这是一个使用示例:

add.sh

#!/bin/sh
echo "$(( + ))"

sub.sh

#!/bin/sh
echo "$(( - ))"

example_import.sh

import_as "add" "math_add"
import_as "sub"

math_add 2 5       # Returns "7"
math_subtract 5 1  # Returns "4" 

我的问题是 eval 这个用例在我执行检查后是否容易受到攻击,或者这个脚本中是否存在可利用的东西?

PS:我知道 eval 被认为是邪恶的,我不想听到这样的回答。如果您认为在 eval 的这个用例中可能存在漏洞,我需要对此用例的具体推理。

如果您相信 import_as 的论点——</code> 和 <code>,以及 </code> 引用的文件内容=11=] -- 以上是安全的。 <code>eval 是邪恶的,因为它允许将数据作为代码进行评估;如果您对这些内容进行硬编码,它们是(可信)代码的一部分,而不是(不可信)数据。

在查看了 Charles Duffy 的精彩回答和评论后,此代码已被评估为更安全:

import_as() { 
  # Charles Duffy's suggestions, including side effect reduction.
  current_lc_ctype="$LC_CTYPE" 
  LC_CTYPE=C

  import_name=""
  import_fnname="${2:-"$import_name"}"

  case "$import_name" in
    *[!/]*) echo "BAD - local directory only."; return ;;
    *) echo "Okay" ;;
  esac

  if test -f "$import_name"; then
    echo "File '$import_name' doesn't exist."
  fi

  case "" in 
    *[!-a-zA-Z0-9_]*) echo "BAD"; return;; 
    *) eval ""'() { '"$(< .sh)"'; }' ;; 
  esac

  # Change LC_CTYPE back to prior to function call
  LC_CTYPE="$current_lc_ctype"
}