Bug 234430 - bc(1) writes error messages to standard output instead of standard error
Summary: bc(1) writes error messages to standard output instead of standard error
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 12.0-STABLE
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-12-26 23:46 UTC by Martijn Dekker
Modified: 2019-01-27 14:07 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martijn Dekker 2018-12-26 23:46:37 UTC
Upon encountering a parsing error, bc(1) passes an error message on to
dc(1), which writes the error message to standard output along with the
normal output.

That is a bug. Error messages should go to standard error instead, as
POSIX specifies:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html#tag_20_09_10

GNU 'bc', Solaris 'bc', and (as of 2017) OpenBSD 'bc' act like POSIX says and write error messages to standard error.

Bizarrely, the exit status of bc(1) is left unspecified:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html#tag_20_09_18
And indeed, all versions of 'bc' exit with status 0 if there is an input
error such as a parsing error, so the exit status cannot be used to
catch it. That leaves examining standard error as the only method for a
program calling bc(1), such as a shell script, to distinguish between an
error state and normal operation. That is, with this bug, there is no
way at all.

The following example shell function transparently hardens bc(1) by
intercepting standard error and exiting the program or subshell if an
error was produced.

bc() {
	_bc_err=$(command -p bc "$@" 2>&1 1>&3)
	[ -z "${_bc_err}" ] && return
	printf '%s\n' "$0: bc(1) caught errors:" "${_bc_err}" 1>&2
	exit 127
} 3>&1

This bug was fixed on OpenBSD 'bc' back in Feburary 2017. I figured FreeBSD would eventually pull in that fix since FreeBSD 'bc' is based on OpenBSD 'bc', but as of FreeBSD 12.0 that hasn't happened.

The OpenBSD patch that fixes the bug is here:
https://marc.info/?l=openbsd-tech&m=148767278323276&w=2
Comment 1 commit-hook freebsd_committer freebsd_triage 2019-01-12 12:35:06 UTC
A commit references this bug:

Author: nyan
Date: Sat Jan 12 12:35:02 UTC 2019
New revision: 342964
URL: https://svnweb.freebsd.org/changeset/base/342964

Log:
  Sync with OpenBSD.

  bc.y: Rev 1.50
  - write parse errors to stderr, prompted by Martijn Dekker
  - we're only interactive if stdout en stderr are a tty as well as stdin

  PR:		234430
  Obtained from:	OpenBSD
  MFC after:	1 week

Changes:
  head/usr.bin/bc/bc.y
Comment 2 commit-hook freebsd_committer freebsd_triage 2019-01-27 13:57:31 UTC
A commit references this bug:

Author: nyan
Date: Sun Jan 27 13:56:44 UTC 2019
New revision: 343490
URL: https://svnweb.freebsd.org/changeset/base/343490

Log:
  MFC: r342964

    Sync with OpenBSD.

    bc.y: Rev 1.50
    - write parse errors to stderr, prompted by Martijn Dekker
    - we're only interactive if stdout en stderr are a tty as well as stdin

  PR:		234430
  Obtained from:	OpenBSD

Changes:
_U  stable/12/
  stable/12/usr.bin/bc/bc.y
Comment 3 commit-hook freebsd_committer freebsd_triage 2019-01-27 13:58:34 UTC
A commit references this bug:

Author: nyan
Date: Sun Jan 27 13:58:07 UTC 2019
New revision: 343491
URL: https://svnweb.freebsd.org/changeset/base/343491

Log:
  MFC: r342964

    Sync with OpenBSD.

    bc.y: Rev 1.50
    - write parse errors to stderr, prompted by Martijn Dekker
    - we're only interactive if stdout en stderr are a tty as well as stdin

  PR:		234430
  Obtained from:	OpenBSD

Changes:
_U  stable/11/
  stable/11/usr.bin/bc/bc.y