我怎样才能避免使用' eval'与每个参考的git-for-ref'?

时间:2015-08-07 10:25:26

标签: git shell security eval

我遇到的git for-each-ref的最高级用途涉及eval。例如,the last example in the git-for-each-ref man page使用eval来执行fmt变量的内容:

#!/bin/sh

fmt='
    r=%(refname)
    # ... omitted, for conciseness ...
    '

eval=`git for-each-ref --shell --format="$fmt" \
    # ... omitted, for conciseness ...
    refs/tags`
eval "$eval"

然而,the use of eval is associated with security risks;尽可能避免它被视为良好做法。

这是一个真实的例子,改编自this answer

#!/bin/sh

fmt='
    ref=%(refname:short)

    if git merge-base --is-ancestor $1 $ref; then
      printf "%s\n" "$ref"
    fi
'

eval "$(git for-each-ref --shell --format="$fmt" refs/heads/)"

在此特定示例中,如何避免使用eval?我已经查看了Zenexer's answer中列出的选项,但我找不到能够解决问题的选项。我正在寻找可移植的(跨不同的shell)解决方案。

1 个答案:

答案 0 :(得分:3)

不要使用eval将数据视为代码,而是让git for-each-ref以易于处理的格式输出数据流。然后,您为该数据编写自定义处理器。

git for-each-ref --format "<values>" \
     # more options
     refs/tags | while read refname object_type <more args> ; do
          <code>
     done

至于你给出的具体例子,这里是一个等效的非eval版本:

#!/bin/bash

if [ $# -ne 1 ]; then
    printf "usage: git branchesthatcontain <rev>\n\n"
    exit 1
fi

rev=$1

git for-each-ref --format='%(refname:short)' refs/heads \
    | while read ref; do 
          if git merge-base --is-ancestor "$rev" "$ref"; then
              echo "$ref"
          fi;
      done

exit $?

我必须补充一点git-for-each-ref确实包含--shell--python--tcl标记,以确保数据被正确转义:这与{中的情况不同{3}}您提到的问题。

the accepted answer也很重要。