Использует ли `eval` для определения функций с текстом из файла зло? - PullRequest
0 голосов
/ 17 сентября 2018

Это дополнительный вопрос к eval cat внутри функции .


Я использую eval для имитации функциональности import из других языков (например,как JavaScript).Это то, что я хотел сделать на своей локальной машине некоторое время, так как я собрал огромную коллекцию файлов сценариев.

Причина в том, что теперь у меня очень большое количество отдельных функций в отдельных файлахи я не хочу постоянно читать файлы с помощью source снова и снова каждый раз, когда я хочу вызвать функциональность.

Это в основном просто для удовольствия, но я не хочу отмахиватьсяя должен когда-либо использовать это в менее случайном контексте:

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

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

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

Вот пример его использования:

add.sh

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

sub.sh

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

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: IЯ понимаю, что eval считается злом, и я не хочу слышать это как ответ.Я хочу конкретное обоснование для этого варианта использования, если вы считаете, что в этом случае eval могут быть эксплойты.

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

После просмотра фантастического ответа и комментария Чарльза Даффи этот код был оценен как более безопасный:

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

  import_name="$1"
  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 "$2" in 
    *[!-a-zA-Z0-9_]*) echo "BAD"; return;; 
    *) eval "$2"'() { '"$(< $1.sh)"'; }' ;; 
  esac

  # Change LC_CTYPE back to prior to function call
  LC_CTYPE="$current_lc_ctype"
}
0 голосов
/ 17 сентября 2018

Если вы доверяете своим аргументам import_as - как $1 и $2, так и содержимому файла, на который ссылается $1 - вышеупомянутое безопасно. eval является злом, поскольку позволяет оценивать данные как код; если вы жестко программируете это содержимое, оно является частью (доверенного) кода, а не (ненадежными) данными.

...