Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SC3021 warning is bogus #2520

Closed
1 of 2 tasks
bhaible opened this issue Jun 18, 2022 · 3 comments
Closed
1 of 2 tasks

SC3021 warning is bogus #2520

bhaible opened this issue Jun 18, 2022 · 3 comments

Comments

@bhaible
Copy link

bhaible commented Jun 18, 2022

For bugs

  • Rule Id (if any, e.g. SC1000): SC3021
  • My shellcheck version (shellcheck --version or 'online'): online
  • I tried on shellcheck.net and verified that this is still a problem on the latest commit
  • It's not reproducible on shellcheck.net, but I think that's because it's an OS, configuration or encoding issue

Here's a snippet or screenshot that shows the problem:

#!/bin/sh
func ()
{
  ofd=3
  {
    echo hi
  } >& $ofd
}
func 3>&1

Here's what shellcheck currently says:

Line 7	SC3021: In POSIX sh, >& is undefined.

Here's what I wanted or expected to see:

Expected output: No warning.

Rationale:

  1. This is perfectly well defined in POSIX. The newest POSIX release is at https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/ . There, the description of sh is at https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/sh.html , and the description of the shell language is at https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/V3_chap02.html . Here, section 2.7 describes redirections, and section 2.7.6 describes the >& operator.

The description says "If word evaluates to one or more digits, the file descriptor denoted by n, or standard input if n is not specified, shall be made to be a copy of the file descriptor denoted by word".

$ofd is a valid word in this place, because: When you look at the grammar in section 2.10.2, the token >&, represented by GREATAND is followed by filename, and filename has the comment "Apply rule 2", and rule 2 says "The expansions specified in [Redirection] shall occur."

  1. The wiki page https://www.shellcheck.net/wiki/SC3021 refers to https://www.shellcheck.net/wiki/SC3020, which cites as the reason "&> is a bash and ksh extension for redirecting both stdout and stderr." But that does not apply to >&. This test (with bash 5.0.17) proves that >& does not redirect stderr:
$ bash -c '{ { echo hi 1>&2; } >& 3 ; } 3>&1' 
hi
$ bash -c '{ { echo hi 1>&2; } >& 3 ; } 3>&1 2>/dev/null' 
  1. The program foo.sh
#!/bin/sh
func ()
{
  ofd=3
  {
    echo hi
  } >&$ofd
}
func 3>&1

prints 'hi', with no error or warning. Tested with

  • bash 5.0.17
  • FreeBSD 13.0 sh
  • NetBSD 9.2 sh
  • OpenBSD 7.0 sh
  • macOS 10.13 sh
  • AIX 7.1 sh
  • Solaris 10 /usr/bin/sh, /usr/5bin/sh, /usr/xpg4/bin/sh
  • Solaris 11.3 sh
  • dash 0.5.10.2
  • BusyBox sh

In other words, there is no actual portability problem with this code.

@bhaible
Copy link
Author

bhaible commented Jun 18, 2022

Note that shellcheck's warning disappears when I write 1>& instead of >&. According to POSIX, these two forms are equivalent (see the sentence "or standard input if n is not specified" cited above). It does not make sense for shellcheck to complain about $ofd in one case but not in the other.

@koalaman
Copy link
Owner

You're right. ShellCheck confused your perfectly portable >& fd with the bash specific extension >& filename. It now only warns if the value is most definitely non-numeric, such as with >& $dir/$file.txt. I've updated the wiki to mention this.

Thanks!

@bhaible
Copy link
Author

bhaible commented Jul 23, 2022

Thanks, the issue is fixed now. And I think ShellCheck handles the bash extensions >& filename and &> filename properly now.

Kangie pushed a commit to Kangie/shellcheck that referenced this issue Feb 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants