From 6141c6a181ed957f8d4291c8a1392328f741e8d5 Mon Sep 17 00:00:00 2001 From: Carlo Cabrera Date: Thu, 10 Jul 2025 03:58:39 +0800 Subject: [PATCH 1/2] 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). --- Library/Homebrew/formulary.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 5a48b25d8b..ac24daddd1 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -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) } From 69ce5edd14f740ccd663c2ade0dd3511b3504c9e Mon Sep 17 00:00:00 2001 From: Carlo Cabrera Date: Thu, 10 Jul 2025 20:25:17 +0800 Subject: [PATCH 2/2] formulary: improve style Co-authored-by: Mike McQuaid --- Library/Homebrew/formulary.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index ac24daddd1..3c1f83d0be 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -139,11 +139,12 @@ module Formulary raise new_exception, "", e.backtrace end ensure - printed_to_stdout = $stdout.string.strip - if printed_to_stdout.present? + # TODO: Make printing to stdout an error so that we can print a tap name. + # See discussion at https://github.com/Homebrew/brew/pull/20226#discussion_r2195886888 + if (printed_to_stdout = $stdout.string.strip.presence) opoo <<~WARNING Formula #{name} attempted to print the following while being loaded: - #{$stdout.string.strip} + #{printed_to_stdout} WARNING end $stdout = old_stdout