From 1efdf6b0145d875b94623bd43a8666378cd007b9 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 14 Feb 2025 19:28:30 +0900 Subject: [PATCH] Subclasses `initialize` must call super Warn wrong code, https://github.com/ruby/logger/pull/100: > Some Ruby apps subclass Logger without running the superclass > constructor, which means that `@level_override` isn't initialized > properly. --- lib/logger.rb | 9 +++++++++ test/logger/test_logger.rb | 15 +++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/lib/logger.rb b/lib/logger.rb index 3e6ab38..4273a43 100644 --- a/lib/logger.rb +++ b/lib/logger.rb @@ -749,6 +749,15 @@ def format_severity(severity) # Guarantee the existence of this ivar even when subclasses don't call the superclass constructor. def level_override + unless defined?(@level_override) + bad = self.class.instance_method(:initialize) + file, line = bad.source_location + Kernel.warn <<~";;;", uplevel: 2 + Logger not initialized properly + #{file}:#{line}: info: #{bad.owner}\##{bad.name}: \ + does not call super probably + ;;; + end @level_override ||= {} end diff --git a/test/logger/test_logger.rb b/test/logger/test_logger.rb index 2023553..ea27fba 100644 --- a/test/logger/test_logger.rb +++ b/test/logger/test_logger.rb @@ -399,4 +399,19 @@ def test_does_not_instantiate_log_device_for_File_NULL l = Logger.new(File::NULL) assert_nil(l.instance_variable_get(:@logdev)) end + + def test_subclass_initialize + bad_logger = Class.new(Logger) {def initialize(*); end}.new(IO::NULL) + line = __LINE__ - 1 + file = Regexp.quote(__FILE__) + assert_warning(/not initialized properly.*\n#{file}:#{line}:/) do + bad_logger.level + end + + good_logger = Class.new(Logger) {def initialize(*); super; end}.new(IO::NULL) + file = Regexp.quote(__FILE__) + assert_warning('') do + good_logger.level + end + end end