diff --git a/doc/jit/zjit.md b/doc/jit/zjit.md index 38124cb7374fed..a284fce8115869 100644 --- a/doc/jit/zjit.md +++ b/doc/jit/zjit.md @@ -1,3 +1,7 @@ +

+ +

+ # ZJIT: ADVANCED RUBY JIT PROTOTYPE ZJIT is a method-based just-in-time (JIT) compiler for Ruby. It uses profile diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c index 6b7e96f622b18b..747f065fbaae3f 100644 --- a/ext/coverage/coverage.c +++ b/ext/coverage/coverage.c @@ -52,17 +52,29 @@ rb_coverage_supported(VALUE self, VALUE _mode) /* * call-seq: - * Coverage.setup => nil - * Coverage.setup(:all) => nil - * Coverage.setup(lines: bool, branches: bool, methods: bool, eval: bool) => nil - * Coverage.setup(oneshot_lines: true) => nil + * Coverage.setup -> nil + * Coverage.setup(type) -> nil + * Coverage.setup(lines: false, branches: false, methods: false, eval: false, oneshot_lines: false) -> nil * - * Set up the coverage measurement. + * Performs setup for coverage measurement, but does not start coverage measurement. + * To start coverage measurement, use Coverage.resume. * - * Note that this method does not start the measurement itself. - * Use Coverage.resume to start the measurement. + * To perform both setup and start coverage measurement, Coverage.start can be used. * - * You may want to use Coverage.start to setup and then start the measurement. + * With argument +type+ given and +type+ is symbol +:all+, enables all types of coverage + * (lines, branches, methods, and eval). + * + * Keyword arguments or hash +type+ can be given with each of the following keys: + * + * - +lines+: Enables line coverage that records the number of times each line was executed. + * If +lines+ is enabled, +oneshot_lines+ cannot be enabled. + * See {Lines Coverage}[rdoc-ref:Coverage@Lines+Coverage]. + * - +branches+: Enables branch coverage that records the number of times each + * branch in each conditional was executed. See {Branches Coverage}[rdoc-ref:Coverage@Branch+Coverage]. + * - +methods+: Enables method coverage that records the number of times each method was exectued. + * See {Methods Coverage}[rdoc-ref:Coverage@Methods+Coverage]. + * - +eval+: Enables coverage for evaluations (e.g. Kernel#eval, Module#class_eval). + * See {Eval Coverage}[rdoc-ref:Coverage@Eval+Coverage]. */ static VALUE rb_coverage_setup(int argc, VALUE *argv, VALUE klass) diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb index f619d93252d950..2f6db44227e4bf 100644 --- a/ext/json/lib/json.rb +++ b/ext/json/lib/json.rb @@ -6,6 +6,15 @@ # # \JSON is a lightweight data-interchange format. # +# \JSON is easy for us humans to read and write, +# and equally simple for machines to read (parse) and write (generate). +# +# \JSON is language-independent, making it an ideal interchange format +# for applications in differing programming languages +# and on differing operating systems. +# +# == \JSON Values +# # A \JSON value is one of the following: # - Double-quoted text: "foo". # - Number: +1+, +1.0+, +2.0e2+. diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb index e5008a24dbf4a6..0fcb635394c433 100644 --- a/lib/rubygems/specification_policy.rb +++ b/lib/rubygems/specification_policy.rb @@ -436,6 +436,7 @@ def validate_values warning "deprecated autorequire specified" if @specification.autorequire @specification.executables.each do |executable| + validate_executable(executable) validate_shebang_line_in(executable) end @@ -449,6 +450,13 @@ def validate_attribute_present(attribute) warning("no #{attribute} specified") if value.nil? || value.empty? end + def validate_executable(executable) + separators = [File::SEPARATOR, File::ALT_SEPARATOR, File::PATH_SEPARATOR].compact.map {|sep| Regexp.escape(sep) }.join + return unless executable.match?(/[\s#{separators}]/) + + error "executable \"#{executable}\" contains invalid characters" + end + def validate_shebang_line_in(executable) executable_path = File.join(@specification.bindir, executable) return if File.read(executable_path, 2) == "#!" diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index e8c2c0eb47027f..7675ade415c608 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -3013,6 +3013,65 @@ def test_validate_executables assert_match "#{w}: bin/exec is missing #! line\n", @ui.error, "error" end + def test_validate_executables_with_space + util_setup_validate + + FileUtils.mkdir_p File.join(@tempdir, "bin") + File.write File.join(@tempdir, "bin", "echo hax"), "#!/usr/bin/env ruby\n" + + @a1.executables = ["echo hax"] + + e = assert_raise Gem::InvalidSpecificationException do + use_ui @ui do + Dir.chdir @tempdir do + @a1.validate + end + end + end + + assert_match "executable \"echo hax\" contains invalid characters", e.message + end + + def test_validate_executables_with_path_separator + util_setup_validate + + FileUtils.mkdir_p File.join(@tempdir, "bin") + File.write File.join(@tempdir, "exe"), "#!/usr/bin/env ruby\n" + + @a1.executables = Gem.win_platform? ? ["..\\exe"] : ["../exe"] + + e = assert_raise Gem::InvalidSpecificationException do + use_ui @ui do + Dir.chdir @tempdir do + @a1.validate + end + end + end + + assert_match "executable \"#{Gem.win_platform? ? "..\\exe" : "../exe"}\" contains invalid characters", e.message + end + + def test_validate_executables_with_path_list_separator + sep = Gem.win_platform? ? ";" : ":" + + util_setup_validate + + FileUtils.mkdir_p File.join(@tempdir, "bin") + File.write File.join(@tempdir, "bin", "foo#{sep}bar"), "#!/usr/bin/env ruby\n" + + @a1.executables = ["foo#{sep}bar"] + + e = assert_raise Gem::InvalidSpecificationException do + use_ui @ui do + Dir.chdir @tempdir do + @a1.validate + end + end + end + + assert_match "executable \"foo#{sep}bar\" contains invalid characters", e.message + end + def test_validate_empty_require_paths util_setup_validate diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index 1729d4404143a6..8714518866c3b4 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -2276,6 +2276,9 @@ fn gen_guard_type_not(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, g /// Compile an identity check with a side exit fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, expected: crate::hir::Const, reason: SideExitReason, state: &FrameState) -> lir::Opnd { + if matches!(reason, SideExitReason::GuardShape(_) ) { + gen_incr_counter(asm, Counter::guard_shape_count); + } let expected_opnd: Opnd = match expected { crate::hir::Const::Value(v) => { Opnd::Value(v) } crate::hir::Const::CInt64(v) => { v.into() }