formulary: prevent formulae from printing to stdout while being loaded

Formulae can execute arbitrary Ruby code when being loaded. In
particular, they can print to stdout with methods like `puts`. This can
break the parsing of output of commands like `brew info --json=v2`.

Let's fix that by capturing the output to stdout, and then printing
those messages to stderr instead (using `opoo` to try to discourage
formula authors from doing this).
This commit is contained in:
Carlo Cabrera 2025-07-10 03:58:39 +08:00 committed by Carlo Cabrera
parent 700d67a85e
commit 6141c6a181
No known key found for this signature in database
GPG Key ID: C74D447FC549A1D0

View File

@ -97,6 +97,11 @@ module Formulary
require "formula"
require "ignorable"
require "stringio"
# Capture stdout to prevent formulae from printing to stdout unexpectedly.
old_stdout = $stdout
$stdout = StringIO.new
mod = Module.new
remove_const(namespace) if const_defined?(namespace)
@ -133,6 +138,15 @@ module Formulary
remove_const(namespace)
raise new_exception, "", e.backtrace
end
ensure
printed_to_stdout = $stdout.string.strip
if printed_to_stdout.present?
opoo <<~WARNING
Formula #{name} attempted to print the following while being loaded:
#{$stdout.string.strip}
WARNING
end
$stdout = old_stdout
end
sig { params(identifier: String).returns(String) }