File with parentheses/brackets in working directory causes eval error












4















I encountered a strange bug today, when running a script in a directory containing a directory with parentheses in it, such as "a()".



Minimal working example



I managed to reduce the bug to the following minimal working example:



Create an empty directory in /tmp and cd into it:



mkdir /tmp/foo
cd /tmp/foo


Create a script named foo.sh in it containing:



foo() {
somevar=1;
case somevar in
aha) echo "something" ;;
*) echo "other" ;;
esac;
};


Run the following command:



eval $(/bin/cat foo.sh)


There should not be any error.



Create a file with parentheses:



touch "a()"


Run the command again:



eval $(/bin/cat foo.sh)


I now get the error:



bash: syntax error near unexpected token `(' 


Why does bash even care about what files are in the directory? Why do parentheses cause an error?



System information:



$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright © 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic


More detailed background and original error:



My problem came from using a script sourcing /usr/share/modules/init/bash from the environment-modules package, as summarized here:



$ dpkg -l environment-modules 
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=============================================================-===================================-===================================-================================================================================================================================
ii environment-modules 4.1.1-1 amd64 Modular system for handling environment variables
$ source /usr/share/modules/init/bash
$ touch "a()"
$ source /usr/share/modules/init/bash
bash: eval: line 43: syntax error near unexpected token `('
bash: eval: line 43: ` a() _mlshdbg='' ;;'









share|improve this question























  • It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.

    – KIAaze
    5 hours ago











  • I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?

    – ilkkachu
    4 hours ago
















4















I encountered a strange bug today, when running a script in a directory containing a directory with parentheses in it, such as "a()".



Minimal working example



I managed to reduce the bug to the following minimal working example:



Create an empty directory in /tmp and cd into it:



mkdir /tmp/foo
cd /tmp/foo


Create a script named foo.sh in it containing:



foo() {
somevar=1;
case somevar in
aha) echo "something" ;;
*) echo "other" ;;
esac;
};


Run the following command:



eval $(/bin/cat foo.sh)


There should not be any error.



Create a file with parentheses:



touch "a()"


Run the command again:



eval $(/bin/cat foo.sh)


I now get the error:



bash: syntax error near unexpected token `(' 


Why does bash even care about what files are in the directory? Why do parentheses cause an error?



System information:



$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright © 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic


More detailed background and original error:



My problem came from using a script sourcing /usr/share/modules/init/bash from the environment-modules package, as summarized here:



$ dpkg -l environment-modules 
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=============================================================-===================================-===================================-================================================================================================================================
ii environment-modules 4.1.1-1 amd64 Modular system for handling environment variables
$ source /usr/share/modules/init/bash
$ touch "a()"
$ source /usr/share/modules/init/bash
bash: eval: line 43: syntax error near unexpected token `('
bash: eval: line 43: ` a() _mlshdbg='' ;;'









share|improve this question























  • It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.

    – KIAaze
    5 hours ago











  • I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?

    – ilkkachu
    4 hours ago














4












4








4


3






I encountered a strange bug today, when running a script in a directory containing a directory with parentheses in it, such as "a()".



Minimal working example



I managed to reduce the bug to the following minimal working example:



Create an empty directory in /tmp and cd into it:



mkdir /tmp/foo
cd /tmp/foo


Create a script named foo.sh in it containing:



foo() {
somevar=1;
case somevar in
aha) echo "something" ;;
*) echo "other" ;;
esac;
};


Run the following command:



eval $(/bin/cat foo.sh)


There should not be any error.



Create a file with parentheses:



touch "a()"


Run the command again:



eval $(/bin/cat foo.sh)


I now get the error:



bash: syntax error near unexpected token `(' 


Why does bash even care about what files are in the directory? Why do parentheses cause an error?



System information:



$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright © 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic


More detailed background and original error:



My problem came from using a script sourcing /usr/share/modules/init/bash from the environment-modules package, as summarized here:



$ dpkg -l environment-modules 
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=============================================================-===================================-===================================-================================================================================================================================
ii environment-modules 4.1.1-1 amd64 Modular system for handling environment variables
$ source /usr/share/modules/init/bash
$ touch "a()"
$ source /usr/share/modules/init/bash
bash: eval: line 43: syntax error near unexpected token `('
bash: eval: line 43: ` a() _mlshdbg='' ;;'









share|improve this question














I encountered a strange bug today, when running a script in a directory containing a directory with parentheses in it, such as "a()".



Minimal working example



I managed to reduce the bug to the following minimal working example:



Create an empty directory in /tmp and cd into it:



mkdir /tmp/foo
cd /tmp/foo


Create a script named foo.sh in it containing:



foo() {
somevar=1;
case somevar in
aha) echo "something" ;;
*) echo "other" ;;
esac;
};


Run the following command:



eval $(/bin/cat foo.sh)


There should not be any error.



Create a file with parentheses:



touch "a()"


Run the command again:



eval $(/bin/cat foo.sh)


I now get the error:



bash: syntax error near unexpected token `(' 


Why does bash even care about what files are in the directory? Why do parentheses cause an error?



System information:



$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright © 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic


More detailed background and original error:



My problem came from using a script sourcing /usr/share/modules/init/bash from the environment-modules package, as summarized here:



$ dpkg -l environment-modules 
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=============================================================-===================================-===================================-================================================================================================================================
ii environment-modules 4.1.1-1 amd64 Modular system for handling environment variables
$ source /usr/share/modules/init/bash
$ touch "a()"
$ source /usr/share/modules/init/bash
bash: eval: line 43: syntax error near unexpected token `('
bash: eval: line 43: ` a() _mlshdbg='' ;;'






bash eval module






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 6 hours ago









KIAazeKIAaze

303213




303213













  • It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.

    – KIAaze
    5 hours ago











  • I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?

    – ilkkachu
    4 hours ago



















  • It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.

    – KIAaze
    5 hours ago











  • I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?

    – ilkkachu
    4 hours ago

















It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.

– KIAaze
5 hours ago





It appears this has already been reported as a bug (and fixed) to the environment-modules package here: github.com/cea-hpc/modules/issues/220 and adding single/double quotes fixes the error. My test script could be simplified to "echo *". But why? Bash and its expansion system still confuses me... I was considering updating my question or answering, but I would really appreciate a clear explanation to what exactly is happening.

– KIAaze
5 hours ago













I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?

– ilkkachu
4 hours ago





I'm tempted to mark this as a duplicate of Why does my shell script choke on whitespace or other special characters?

– ilkkachu
4 hours ago










1 Answer
1






active

oldest

votes


















8














This is neither strange or a bug in bash (it does seem to be a bug in /usr/share/modules/init/bash though). You are using an unquoted command substitution together with eval. The string that is the result of the command substitution will, since it is unquoted, undergo word splitting and filename generation (globbing). The *) in the code matches the filename a(), so it is replace by this filename.



Running your example under set -x highlights this:



$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
bash: syntax error near unexpected token `('


The same thing in the yash shell:



$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
eval:1: syntax error: `)' is missing
eval:1: syntax error: `esac' is missing
eval:1: syntax error: `}' is missing


And with ksh93:



$ eval $(cat foo.sh)
+ cat foo.sh
+ eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
ksh93: eval: syntax error: `(' unexpected


And dash:



$ eval $(cat foo.sh)
+ cat foo.sh
+ eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
dash: 1: eval: Syntax error: "(" unexpected (expecting ")")


Only the zsh would handle this as it does not perform the globbing:



$ eval $(cat foo.sh)
+zsh:2> cat foo.sh
+zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'


The correct way to handle this would be to source the foo.sh script:



. ./foo.sh


There is really no reason to use eval "$(cat foo.sh)" as far as I can see.



This is also a code injection vulnerability:



$ touch '*) echo "hello" ;; *)'
$ eval $(cat foo.sh)
$ declare -f foo
foo ()
{
somevar=1;
case somevar in
aha)
echo "something"
;;
*)
echo "hello"
;;
*)
echo "other"
;;
esac
}


Another way of breaking this command easily without creating a specially named file, is to set the IFS variable to a set of characters other than the default:



$ IFS=';{} '
+ IFS=';{} '
$ eval $(cat foo.sh)
++ cat foo.sh
+ eval 'foo()' '
' somevar=1 '
' case somevar 'in
' 'aha)' echo '"something"' '' '
' '*)' echo '"other"' '' '
' esac '
' ''
bash: syntax error near unexpected token `somevar=1'


This breaks it because of the word-splitting step rather than the file globbing step in the evaluation of the argument to eval. With IFS=';{} ', each of those characters would be used to split the text in foo.sh up into words (and those characters would then be removed from the string).



Not even zsh would be immune to this:



$ IFS=';{} '
+zsh:2> IFS=';{} '
$ eval $(cat foo.sh)
+zsh:3> cat foo.sh
+zsh:3> eval 'foo()' $'n' 'somevar=1' $'n' case somevar $'inn' 'aha)' echo '"something"' '' $'n' '*)' echo '"other"' '' $'n' esac $'n' '' ''
zsh: parse error near `)'


Related:




  • Security implications of forgetting to quote a variable in bash/POSIX shells

  • When is double-quoting necessary?

  • Why does my shell script choke on whitespace or other special characters?






share|improve this answer

























    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "106"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f501188%2ffile-with-parentheses-brackets-in-working-directory-causes-eval-error%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    8














    This is neither strange or a bug in bash (it does seem to be a bug in /usr/share/modules/init/bash though). You are using an unquoted command substitution together with eval. The string that is the result of the command substitution will, since it is unquoted, undergo word splitting and filename generation (globbing). The *) in the code matches the filename a(), so it is replace by this filename.



    Running your example under set -x highlights this:



    $ eval $(cat foo.sh)
    ++ cat foo.sh
    + eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
    bash: syntax error near unexpected token `('


    The same thing in the yash shell:



    $ eval $(cat foo.sh)
    + cat foo.sh
    + eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
    eval:1: syntax error: `)' is missing
    eval:1: syntax error: `esac' is missing
    eval:1: syntax error: `}' is missing


    And with ksh93:



    $ eval $(cat foo.sh)
    + cat foo.sh
    + eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
    ksh93: eval: syntax error: `(' unexpected


    And dash:



    $ eval $(cat foo.sh)
    + cat foo.sh
    + eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
    dash: 1: eval: Syntax error: "(" unexpected (expecting ")")


    Only the zsh would handle this as it does not perform the globbing:



    $ eval $(cat foo.sh)
    +zsh:2> cat foo.sh
    +zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'


    The correct way to handle this would be to source the foo.sh script:



    . ./foo.sh


    There is really no reason to use eval "$(cat foo.sh)" as far as I can see.



    This is also a code injection vulnerability:



    $ touch '*) echo "hello" ;; *)'
    $ eval $(cat foo.sh)
    $ declare -f foo
    foo ()
    {
    somevar=1;
    case somevar in
    aha)
    echo "something"
    ;;
    *)
    echo "hello"
    ;;
    *)
    echo "other"
    ;;
    esac
    }


    Another way of breaking this command easily without creating a specially named file, is to set the IFS variable to a set of characters other than the default:



    $ IFS=';{} '
    + IFS=';{} '
    $ eval $(cat foo.sh)
    ++ cat foo.sh
    + eval 'foo()' '
    ' somevar=1 '
    ' case somevar 'in
    ' 'aha)' echo '"something"' '' '
    ' '*)' echo '"other"' '' '
    ' esac '
    ' ''
    bash: syntax error near unexpected token `somevar=1'


    This breaks it because of the word-splitting step rather than the file globbing step in the evaluation of the argument to eval. With IFS=';{} ', each of those characters would be used to split the text in foo.sh up into words (and those characters would then be removed from the string).



    Not even zsh would be immune to this:



    $ IFS=';{} '
    +zsh:2> IFS=';{} '
    $ eval $(cat foo.sh)
    +zsh:3> cat foo.sh
    +zsh:3> eval 'foo()' $'n' 'somevar=1' $'n' case somevar $'inn' 'aha)' echo '"something"' '' $'n' '*)' echo '"other"' '' $'n' esac $'n' '' ''
    zsh: parse error near `)'


    Related:




    • Security implications of forgetting to quote a variable in bash/POSIX shells

    • When is double-quoting necessary?

    • Why does my shell script choke on whitespace or other special characters?






    share|improve this answer






























      8














      This is neither strange or a bug in bash (it does seem to be a bug in /usr/share/modules/init/bash though). You are using an unquoted command substitution together with eval. The string that is the result of the command substitution will, since it is unquoted, undergo word splitting and filename generation (globbing). The *) in the code matches the filename a(), so it is replace by this filename.



      Running your example under set -x highlights this:



      $ eval $(cat foo.sh)
      ++ cat foo.sh
      + eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
      bash: syntax error near unexpected token `('


      The same thing in the yash shell:



      $ eval $(cat foo.sh)
      + cat foo.sh
      + eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
      eval:1: syntax error: `)' is missing
      eval:1: syntax error: `esac' is missing
      eval:1: syntax error: `}' is missing


      And with ksh93:



      $ eval $(cat foo.sh)
      + cat foo.sh
      + eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
      ksh93: eval: syntax error: `(' unexpected


      And dash:



      $ eval $(cat foo.sh)
      + cat foo.sh
      + eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
      dash: 1: eval: Syntax error: "(" unexpected (expecting ")")


      Only the zsh would handle this as it does not perform the globbing:



      $ eval $(cat foo.sh)
      +zsh:2> cat foo.sh
      +zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'


      The correct way to handle this would be to source the foo.sh script:



      . ./foo.sh


      There is really no reason to use eval "$(cat foo.sh)" as far as I can see.



      This is also a code injection vulnerability:



      $ touch '*) echo "hello" ;; *)'
      $ eval $(cat foo.sh)
      $ declare -f foo
      foo ()
      {
      somevar=1;
      case somevar in
      aha)
      echo "something"
      ;;
      *)
      echo "hello"
      ;;
      *)
      echo "other"
      ;;
      esac
      }


      Another way of breaking this command easily without creating a specially named file, is to set the IFS variable to a set of characters other than the default:



      $ IFS=';{} '
      + IFS=';{} '
      $ eval $(cat foo.sh)
      ++ cat foo.sh
      + eval 'foo()' '
      ' somevar=1 '
      ' case somevar 'in
      ' 'aha)' echo '"something"' '' '
      ' '*)' echo '"other"' '' '
      ' esac '
      ' ''
      bash: syntax error near unexpected token `somevar=1'


      This breaks it because of the word-splitting step rather than the file globbing step in the evaluation of the argument to eval. With IFS=';{} ', each of those characters would be used to split the text in foo.sh up into words (and those characters would then be removed from the string).



      Not even zsh would be immune to this:



      $ IFS=';{} '
      +zsh:2> IFS=';{} '
      $ eval $(cat foo.sh)
      +zsh:3> cat foo.sh
      +zsh:3> eval 'foo()' $'n' 'somevar=1' $'n' case somevar $'inn' 'aha)' echo '"something"' '' $'n' '*)' echo '"other"' '' $'n' esac $'n' '' ''
      zsh: parse error near `)'


      Related:




      • Security implications of forgetting to quote a variable in bash/POSIX shells

      • When is double-quoting necessary?

      • Why does my shell script choke on whitespace or other special characters?






      share|improve this answer




























        8












        8








        8







        This is neither strange or a bug in bash (it does seem to be a bug in /usr/share/modules/init/bash though). You are using an unquoted command substitution together with eval. The string that is the result of the command substitution will, since it is unquoted, undergo word splitting and filename generation (globbing). The *) in the code matches the filename a(), so it is replace by this filename.



        Running your example under set -x highlights this:



        $ eval $(cat foo.sh)
        ++ cat foo.sh
        + eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
        bash: syntax error near unexpected token `('


        The same thing in the yash shell:



        $ eval $(cat foo.sh)
        + cat foo.sh
        + eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
        eval:1: syntax error: `)' is missing
        eval:1: syntax error: `esac' is missing
        eval:1: syntax error: `}' is missing


        And with ksh93:



        $ eval $(cat foo.sh)
        + cat foo.sh
        + eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
        ksh93: eval: syntax error: `(' unexpected


        And dash:



        $ eval $(cat foo.sh)
        + cat foo.sh
        + eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
        dash: 1: eval: Syntax error: "(" unexpected (expecting ")")


        Only the zsh would handle this as it does not perform the globbing:



        $ eval $(cat foo.sh)
        +zsh:2> cat foo.sh
        +zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'


        The correct way to handle this would be to source the foo.sh script:



        . ./foo.sh


        There is really no reason to use eval "$(cat foo.sh)" as far as I can see.



        This is also a code injection vulnerability:



        $ touch '*) echo "hello" ;; *)'
        $ eval $(cat foo.sh)
        $ declare -f foo
        foo ()
        {
        somevar=1;
        case somevar in
        aha)
        echo "something"
        ;;
        *)
        echo "hello"
        ;;
        *)
        echo "other"
        ;;
        esac
        }


        Another way of breaking this command easily without creating a specially named file, is to set the IFS variable to a set of characters other than the default:



        $ IFS=';{} '
        + IFS=';{} '
        $ eval $(cat foo.sh)
        ++ cat foo.sh
        + eval 'foo()' '
        ' somevar=1 '
        ' case somevar 'in
        ' 'aha)' echo '"something"' '' '
        ' '*)' echo '"other"' '' '
        ' esac '
        ' ''
        bash: syntax error near unexpected token `somevar=1'


        This breaks it because of the word-splitting step rather than the file globbing step in the evaluation of the argument to eval. With IFS=';{} ', each of those characters would be used to split the text in foo.sh up into words (and those characters would then be removed from the string).



        Not even zsh would be immune to this:



        $ IFS=';{} '
        +zsh:2> IFS=';{} '
        $ eval $(cat foo.sh)
        +zsh:3> cat foo.sh
        +zsh:3> eval 'foo()' $'n' 'somevar=1' $'n' case somevar $'inn' 'aha)' echo '"something"' '' $'n' '*)' echo '"other"' '' $'n' esac $'n' '' ''
        zsh: parse error near `)'


        Related:




        • Security implications of forgetting to quote a variable in bash/POSIX shells

        • When is double-quoting necessary?

        • Why does my shell script choke on whitespace or other special characters?






        share|improve this answer















        This is neither strange or a bug in bash (it does seem to be a bug in /usr/share/modules/init/bash though). You are using an unquoted command substitution together with eval. The string that is the result of the command substitution will, since it is unquoted, undergo word splitting and filename generation (globbing). The *) in the code matches the filename a(), so it is replace by this filename.



        Running your example under set -x highlights this:



        $ eval $(cat foo.sh)
        ++ cat foo.sh
        + eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
        bash: syntax error near unexpected token `('


        The same thing in the yash shell:



        $ eval $(cat foo.sh)
        + cat foo.sh
        + eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
        eval:1: syntax error: `)' is missing
        eval:1: syntax error: `esac' is missing
        eval:1: syntax error: `}' is missing


        And with ksh93:



        $ eval $(cat foo.sh)
        + cat foo.sh
        + eval 'foo()' '{' somevar='1;' case somevar in 'aha)' echo '"something"' ';;' 'a()' echo '"other"' ';;' 'esac;' '};'
        ksh93: eval: syntax error: `(' unexpected


        And dash:



        $ eval $(cat foo.sh)
        + cat foo.sh
        + eval foo() { somevar=1; case somevar in aha) echo "something" ;; a() echo "other" ;; esac; };
        dash: 1: eval: Syntax error: "(" unexpected (expecting ")")


        Only the zsh would handle this as it does not perform the globbing:



        $ eval $(cat foo.sh)
        +zsh:2> cat foo.sh
        +zsh:2> eval 'foo()' '{' 'somevar=1;' case somevar in 'aha)' echo '"something"' ';;' '*)' echo '"other"' ';;' 'esac;' '};'


        The correct way to handle this would be to source the foo.sh script:



        . ./foo.sh


        There is really no reason to use eval "$(cat foo.sh)" as far as I can see.



        This is also a code injection vulnerability:



        $ touch '*) echo "hello" ;; *)'
        $ eval $(cat foo.sh)
        $ declare -f foo
        foo ()
        {
        somevar=1;
        case somevar in
        aha)
        echo "something"
        ;;
        *)
        echo "hello"
        ;;
        *)
        echo "other"
        ;;
        esac
        }


        Another way of breaking this command easily without creating a specially named file, is to set the IFS variable to a set of characters other than the default:



        $ IFS=';{} '
        + IFS=';{} '
        $ eval $(cat foo.sh)
        ++ cat foo.sh
        + eval 'foo()' '
        ' somevar=1 '
        ' case somevar 'in
        ' 'aha)' echo '"something"' '' '
        ' '*)' echo '"other"' '' '
        ' esac '
        ' ''
        bash: syntax error near unexpected token `somevar=1'


        This breaks it because of the word-splitting step rather than the file globbing step in the evaluation of the argument to eval. With IFS=';{} ', each of those characters would be used to split the text in foo.sh up into words (and those characters would then be removed from the string).



        Not even zsh would be immune to this:



        $ IFS=';{} '
        +zsh:2> IFS=';{} '
        $ eval $(cat foo.sh)
        +zsh:3> cat foo.sh
        +zsh:3> eval 'foo()' $'n' 'somevar=1' $'n' case somevar $'inn' 'aha)' echo '"something"' '' $'n' '*)' echo '"other"' '' $'n' esac $'n' '' ''
        zsh: parse error near `)'


        Related:




        • Security implications of forgetting to quote a variable in bash/POSIX shells

        • When is double-quoting necessary?

        • Why does my shell script choke on whitespace or other special characters?







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 4 hours ago

























        answered 5 hours ago









        KusalanandaKusalananda

        130k17247406




        130k17247406






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f501188%2ffile-with-parentheses-brackets-in-working-directory-causes-eval-error%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How to label and detect the document text images

            Vallis Paradisi

            Tabula Rosettana