This is an automated email from the ASF dual-hosted git repository.

nihaljain pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-3 by this push:
     new 52bbb17358a HBASE-28660 list_namespace not working after an incorrect 
user input (#7931) (#8020)
52bbb17358a is described below

commit 52bbb17358a8a2198031a3d724ef183912d92919
Author: Arvind Kandpal <[email protected]>
AuthorDate: Thu Apr 2 16:08:25 2026 +0530

    HBASE-28660 list_namespace not working after an incorrect user input 
(#7931) (#8020)
    
    Reviewed-by: Vaibhav Joshi <[email protected]>
    (cherry picked from commit 2e42e4cdc9dbf8774aa63c305f024d5b16e3b5a4)
    
    Signed-off-by: Duo Zhang <[email protected]>
    Signed-off-by: Nihal Jain <[email protected]>
    Signed-off-by: Xiao Liu <[email protected]>
---
 hbase-shell/src/main/ruby/irb/hirb.rb              | 29 ++++++++
 .../src/test/ruby/shell/general_test_cluster.rb    | 77 ++++++++++++++++++++++
 2 files changed, 106 insertions(+)

diff --git a/hbase-shell/src/main/ruby/irb/hirb.rb 
b/hbase-shell/src/main/ruby/irb/hirb.rb
index 73b0ee91a11..34638f228a9 100644
--- a/hbase-shell/src/main/ruby/irb/hirb.rb
+++ b/hbase-shell/src/main/ruby/irb/hirb.rb
@@ -23,6 +23,10 @@ module IRB
 
   # Subclass of IRB so can intercept methods
   class HIRB < Irb
+    def self.command_names
+      @command_names ||= ::Shell.commands.keys.map(&:to_sym).freeze
+    end
+
     def initialize(workspace = nil, interactive = true, input_method = nil)
       # This is ugly.  Our 'help' method above provokes the following message
       # on irb construction: 'irb: warn: can't alias help from irb_help.'
@@ -53,6 +57,14 @@ module IRB
       $stdout = STDOUT
     end
 
+    def set_context_workspace(workspace)
+      if @context.respond_to?(:workspace=)
+        @context.workspace = workspace
+      else
+        @context.instance_variable_set(:@workspace, workspace)
+      end
+    end
+
     def output_value(omit = false)
       # Suppress output if last_value is 'nil'
       # Otherwise, when user types help, get ugly 'nil'
@@ -163,6 +175,23 @@ module IRB
           else
             exc = nil
             next
+          ensure
+            # HBASE-28660: Prevent command shadowing by incorrectly parsed 
local variables
+            cmd_names = self.class.command_names
+            workspace_binding = @context.workspace.binding
+            shadowing_vars = workspace_binding.local_variables & cmd_names
+
+            if shadowing_vars.any?
+              shadowing_vars.each do |var|
+                warn "WARN: '#{var}' is a reserved HBase command. Local 
variable assignment ignored."
+              end
+
+              new_binding = @context.workspace.main.get_binding
+              (workspace_binding.local_variables - shadowing_vars).each do 
|var|
+                new_binding.local_variable_set(var, 
workspace_binding.local_variable_get(var))
+              end
+              set_context_workspace(::IRB::WorkSpace.new(new_binding))
+            end
           end
           handle_exception(exc)
           @context.workspace.local_variable_set(:_, exc)
diff --git a/hbase-shell/src/test/ruby/shell/general_test_cluster.rb 
b/hbase-shell/src/test/ruby/shell/general_test_cluster.rb
index dfbadbeb65a..e49dd6e2aaf 100644
--- a/hbase-shell/src/test/ruby/shell/general_test_cluster.rb
+++ b/hbase-shell/src/test/ruby/shell/general_test_cluster.rb
@@ -19,6 +19,8 @@
 
 require 'hbase_constants'
 require 'hbase_shell'
+require 'irb/hirb'
+require 'stringio'
 
 class ShellTest < Test::Unit::TestCase
   include Hbase::TestHelpers
@@ -149,4 +151,79 @@ class ShellTest < Test::Unit::TestCase
     # create a table that exists
     @shell.command('create', 'nothrow_table', 'family_1')
   end
+
+  
#-----------------------------------------------------------------------------
+
+  class MockInputMethod < IRB::InputMethod
+    def initialize(lines)
+      super()
+      @lines = lines
+    end
+    def gets
+      @lines.shift
+    end
+    def eof?
+      @lines.empty?
+    end
+    def encoding
+      Encoding::UTF_8
+    end
+    def readable_after_eof?
+      false
+    end
+  end
+
+  define_test 'Shell::Shell should prevent HBase commands from being shadowed 
by local variables (HBASE-28660)' do
+    workspace = @shell.get_workspace
+    IRB.setup(__FILE__) unless IRB.conf[:IRB_NAME]
+
+    lines = [
+      "list = 10\n",
+      "list_namespace, 'ns.*'\n",
+      "list_snapshots, 'snap01'\n",
+      "scan = 20\n",
+      "processlist = 30\n",
+      "my_var = 5\n"
+    ]
+
+    input_method = MockInputMethod.new(lines)
+    hirb = IRB::HIRB.new(workspace, true, input_method)
+
+    hirb.context.prompt_i = ""
+    hirb.context.prompt_s = ""
+    hirb.context.prompt_c = ""
+    hirb.context.prompt_n = ""
+    hirb.context.return_format = ""
+    hirb.context.echo = false
+
+    old_stderr = $stderr
+    $stderr = StringIO.new
+    err_output = ""
+    begin
+      capture_stdout do
+        hirb.eval_input
+      end
+    ensure
+      err_output = $stderr.string
+      $stderr = old_stderr
+    end
+
+    final_workspace = hirb.context.workspace
+    final_vars = final_workspace.binding.local_variables
+
+    assert(final_vars.include?(:my_var), "Valid variables should be preserved")
+    assert_equal(5, final_workspace.binding.local_variable_get(:my_var))
+
+    assert(!final_vars.include?(:list), "Command 'list' should not be 
shadowed")
+    assert(!final_vars.include?(:list_namespace), "Command 'list_namespace' 
should not be shadowed")
+    assert(!final_vars.include?(:list_snapshots), "Command 'list_snapshots' 
should not be shadowed")
+    assert(!final_vars.include?(:scan), "Command 'scan' should not be 
shadowed")
+    assert(!final_vars.include?(:processlist), "Command 'processlist' should 
not be shadowed")
+
+    assert_match(/WARN: 'list' is a reserved HBase command/, err_output)
+    assert_match(/WARN: 'list_namespace' is a reserved HBase command/, 
err_output)
+    assert_match(/WARN: 'list_snapshots' is a reserved HBase command/, 
err_output)
+    assert_match(/WARN: 'scan' is a reserved HBase command/, err_output)
+    assert_match(/WARN: 'processlist' is a reserved HBase command/, err_output)
+  end
 end

Reply via email to