flaw_detector 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,43 @@
1
+ #ifndef VM_CORE_SUBSET_H
2
+ #define VM_CORE_SUBSET_H
3
+
4
+ /* to avoid warning */
5
+ struct rb_thread_struct;
6
+ struct rb_control_frame_struct;
7
+ typedef int rb_iseq_t;
8
+ typedef int rb_method_entry_t;
9
+
10
+ /* rb_call_info_t contains calling information including inline cache */
11
+ typedef struct rb_call_info_struct {
12
+ /* fixed at compile time */
13
+ ID mid;
14
+ VALUE flag;
15
+ int orig_argc;
16
+ rb_iseq_t *blockiseq;
17
+
18
+ /* inline cache: keys */
19
+ VALUE vmstat;
20
+ VALUE klass;
21
+
22
+ /* inline cache: values */
23
+ const rb_method_entry_t *me;
24
+ VALUE defined_class;
25
+
26
+ /* temporary values for method calling */
27
+ int argc;
28
+ struct rb_block_struct *blockptr;
29
+ VALUE recv;
30
+ union {
31
+ int opt_pc; /* used by iseq */
32
+ long index; /* used by ivar */
33
+ int missing_reason; /* used by method_missing */
34
+ int inc_sp; /* used by cfunc */
35
+ } aux;
36
+
37
+ VALUE (*call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci);
38
+ } rb_call_info_t;
39
+ typedef rb_call_info_t *CALL_INFO;
40
+
41
+ #define VM_CALL_ARGS_BLOCKARG (0x01 << 2) //copy from vm_core.h
42
+
43
+ #endif /* VM_CORE_SUBSET_H */
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.email = ["dbc.ginriki@gmail.com"]
10
10
  s.homepage = ""
11
11
  s.summary = %q{The tool to detect code's flaw with static analysis}
12
- s.description = %q{The tool detects code's flaw, which should be fixed, with static analysis of RubyVM bytecode. Therefore, it works for only ruby 1.9.x. ASAP, I will support ruby 2.0.x .}
12
+ s.description = %q{The tool detects code's flaw, which should be fixed, with static analysis of RubyVM bytecode. Therefore, it works for only ruby 1.9.x or 2.0.x .}
13
13
 
14
14
  s.rubyforge_project = "flaw detector"
15
15
 
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
  s.extensions = ["ext/insns_ext/extconf.rb"]
21
- s.required_ruby_version = "~> 1.9.0"
21
+ s.required_ruby_version = "> 1.9.0"
22
22
 
23
23
  # specify any dependencies here; for example:
24
24
  s.add_development_dependency "rspec"
data/lib/flaw_detector.rb CHANGED
@@ -6,6 +6,7 @@ require "flaw_detector/detector/nil_false_path_flow"
6
6
  require "flaw_detector/code_model/code_document"
7
7
  require "flaw_detector/code_model/insns_frame"
8
8
  require "flaw_detector/code_model/cfg_node"
9
+ require "flaw_detector/iseq/instruction_container"
9
10
  require File.expand_path("../../ext/insns_ext/insn_ext.rb", __FILE__)
10
11
 
11
12
  module FlawDetector
@@ -29,9 +30,17 @@ module FlawDetector
29
30
  INSNS_OF_BRANCH = ["branchif", "branchunless"]
30
31
 
31
32
  def parse(code_str, filepath="<compiled>")
32
- isqns = RubyVM::InstructionSequence.new(code_str)
33
- data = iseq_parse(isqns.to_a)
34
- CodeDocument.create(data, filepath)
33
+ tmp_compile_option = RubyVM::InstructionSequence.compile_option
34
+ doc = nil
35
+ begin
36
+ RubyVM::InstructionSequence.compile_option = false
37
+ isqns = RubyVM::InstructionSequence.compile(code_str)
38
+ data = iseq_parse(isqns.to_a)
39
+ doc = CodeDocument.create(data, filepath)
40
+ ensure
41
+ RubyVM::InstructionSequence.compile_option = tmp_compile_option
42
+ end
43
+ return doc
35
44
  end
36
45
 
37
46
  def parse_file(file)
@@ -81,16 +90,15 @@ module FlawDetector
81
90
  iseq[13].each do |mixed|
82
91
  case mixed
83
92
  when Array # instruction
84
- insns << mixed
93
+ insns << Iseq::InstructionContainer.new(mixed, header)
85
94
  opcode = mixed.first.to_s
86
95
  if INSNS_HAVE_ISEQ_IN_OPERAND.keys.include?(opcode)
87
- operand_num = INSNS_HAVE_ISEQ_IN_OPERAND[opcode]
88
- iseq_in_operand = iseq_parse(mixed[operand_num])
96
+ iseq_in_operand = iseq_parse(insns.last[:blockptr])
89
97
  insn_pos = insns.count-1
90
98
  insns_pos_to_operand_iseq[insn_pos] = iseq_in_operand
91
99
 
92
100
  #replace to link
93
- mixed[operand_num] = insn_pos
101
+ #mixed[operand_num] = insn_pos
94
102
 
95
103
  if insns_pos_to_operand_iseq[insn_pos] &&
96
104
  insns_pos_to_operand_iseq[insn_pos][:header][:type] == ISeqHeader::TYPE_BLOCK
@@ -42,13 +42,13 @@ module FlawDetector
42
42
  klass_specified_edge = nil
43
43
  case obj_insn[0]
44
44
  when :send
45
- if argnum == 0 && RCEV_KLASS_OF_METHODS.has_key?(obj_insn[1]) #varnum is the receiver and method is a nil check
45
+ if argnum == 0 && RCEV_KLASS_OF_METHODS.has_key?(obj_insn[:mid]) #varnum is the receiver and method is a nil check
46
46
  next_obj_index,next_argnum = frame.find_use_insn_index_of_ret(obj_index, obj_insn)
47
47
  next_obj_insn = frame.raw_block_data[:body][:insns][next_obj_index]
48
48
  case next_obj_insn[0]
49
49
  when :branchif, :branchunless
50
- klass_specified_edge = RCEV_KLASS_OF_METHODS[obj_insn[1]][:message][next_obj_insn[0]]
51
- klass = RCEV_KLASS_OF_METHODS[obj_insn[1]][:klass]
50
+ klass_specified_edge = RCEV_KLASS_OF_METHODS[obj_insn[:mid]][:message][next_obj_insn[0]]
51
+ klass = RCEV_KLASS_OF_METHODS[obj_insn[:mid]][:klass]
52
52
  end
53
53
  end
54
54
  when :branchif, :branchunless
@@ -120,8 +120,10 @@ module FlawDetector
120
120
  return result
121
121
  end
122
122
 
123
- # _variable_ :: nil variable on node
124
- # return: check_end?, detected ngs
123
+ # @param variable [Hash] nil variable on node
124
+ # @return [Boolean] check_end?
125
+ # @return [Array] detected ngs
126
+ # @todo remove false positive detection of neither compareable or replacement operator such as "<<"
125
127
  def check_nil_var_ref(node, variable)
126
128
  ng_list = [] # each element has keys: {:variable, :index, :frame}
127
129
  unless node.prev_nodes.first == node.prev_nodes.last
@@ -147,8 +149,8 @@ module FlawDetector
147
149
  use_insn = frame.insns[use_index]
148
150
  case use_insn[0]
149
151
  when :send
150
- use_insn[1]
151
- if use_argnum == 0 && !NIL_METHODS.include?(use_insn[1])
152
+ if (use_argnum == 0 && !NIL_METHODS.include?(use_insn[:mid])) ||
153
+ (use_argnum == 1 && CALC_CODE.values.include?(use_insn[:mid]) && !NIL_METHODS.include?(use_insn[:mid]))
152
154
  ng_list << {:variable => variable, :index => use_index, :frame => frame}
153
155
  end
154
156
  when *(CALC_CODE.keys)
@@ -0,0 +1,83 @@
1
+ module FlawDetector
2
+ module Iseq
3
+ class InstructionContainer
4
+ attr_reader :insn
5
+ def initialize(insn, header)
6
+ @insn = insn
7
+ @major_version = header[:major]
8
+ end
9
+
10
+ def major_version
11
+ @major_version
12
+ end
13
+
14
+ def inspect
15
+ @insn.inspect
16
+ end
17
+
18
+ def [](param)
19
+ case param
20
+ when Fixnum
21
+ return @insn[param]
22
+ when Range
23
+ return @insn[param]
24
+ when Symbol
25
+ if param == :opcode
26
+ return @insn[0]
27
+ else
28
+ return send("symbol_#{self[:opcode]}_v#{self.major_version}", param)
29
+ end
30
+ else
31
+ raise "unknown param:#{param}"
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def symbol_send_v1(param)
38
+ case param
39
+ when :mid
40
+ return @insn[1]
41
+ when :blockptr
42
+ return @insn[3]
43
+ end
44
+ end
45
+
46
+ def symbol_send_v2(param)
47
+ case param
48
+ when :mid
49
+ return @insn[1][:mid]
50
+ when :blockptr
51
+ return @insn[1][:blockptr]
52
+ else
53
+ return symbol_send_v1(param)
54
+ end
55
+ end
56
+
57
+ def symbol_putiseq_v1(param)
58
+ case param
59
+ when :blockptr
60
+ return @insn[1]
61
+ end
62
+ end
63
+
64
+ def symbol_defineclass_v1(param)
65
+ case param
66
+ when :blockptr
67
+ return @insn[2]
68
+ end
69
+ end
70
+
71
+ def symbol_invokesuper_v1(param)
72
+ case param
73
+ when :blockptr
74
+ return @insn[2]
75
+ end
76
+ end
77
+
78
+ alias :symbol_invokesuper_v2 :symbol_invokesuper_v1
79
+ alias :symbol_putiseq_v2 :symbol_putiseq_v1
80
+ alias :symbol_defineclass_v2 :symbol_defineclass_v1
81
+ end
82
+ end
83
+ end
@@ -11,9 +11,9 @@ module FlawDetector
11
11
  :details => "This method contains a redundant check of a known false value against the constant false."
12
12
  },
13
13
  "RCN_REDUNDANT_FALSECHECK_OF_TRUE_VALUE" => {
14
- :short_desc => "Redundant falsecheck of value known to be false",
15
- :long_desc => "Redundant falsecheck of %{0} which is known to be false in LINE:%{1}",
16
- :details => "This method contains a redundant check of a known false value against the constant false."
14
+ :short_desc => "Redundant falsecheck of value known to be true",
15
+ :long_desc => "Redundant falsecheck of %{0} which is known to be true in LINE:%{1}",
16
+ :details => "This method contains a redundant check of a true value against the constant false."
17
17
  },
18
18
  "NP_ALWAYS_FALSE" => {
19
19
  :short_desc => "False value missing method received",
@@ -1,3 +1,3 @@
1
1
  module FlawDetector
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -1,38 +1,39 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: flaw_detector
3
- version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
6
5
  platform: ruby
7
- authors:
6
+ authors:
8
7
  - Rikiya Ayukawa
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
-
13
- date: 2013-04-28 00:00:00 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
11
+ date: 2013-06-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
16
14
  name: rspec
17
- prerelease: false
18
- requirement: &id001 !ruby/object:Gem::Requirement
19
- none: false
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0"
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
24
20
  type: :development
25
- version_requirements: *id001
26
- description: The tool detects code's flaw, which should be fixed, with static analysis of RubyVM bytecode. Therefore, it works for only ruby 1.9.x. ASAP, I will support ruby 2.0.x .
27
- email:
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: The tool detects code's flaw, which should be fixed, with static analysis
28
+ of RubyVM bytecode. Therefore, it works for only ruby 1.9.x or 2.0.x .
29
+ email:
28
30
  - dbc.ginriki@gmail.com
29
- executables:
31
+ executables:
30
32
  - flaw_detector
31
- extensions:
33
+ extensions:
32
34
  - ext/insns_ext/extconf.rb
33
35
  extra_rdoc_files: []
34
-
35
- files:
36
+ files:
36
37
  - .gitignore
37
38
  - .travis.yml
38
39
  - Gemfile
@@ -42,9 +43,15 @@ files:
42
43
  - bin/flaw_detector
43
44
  - ext/insns_ext/extconf.rb
44
45
  - ext/insns_ext/insn_ext.rb
45
- - ext/insns_ext/insns.inc
46
- - ext/insns_ext/insns_ext.c
47
- - ext/insns_ext/insns_info.inc
46
+ - ext/insns_ext/insns/1.9/BSDL
47
+ - ext/insns_ext/insns/1.9/insns.inc
48
+ - ext/insns_ext/insns/1.9/insns_ext.c
49
+ - ext/insns_ext/insns/1.9/insns_info.inc
50
+ - ext/insns_ext/insns/2.0/BSDL
51
+ - ext/insns_ext/insns/2.0/insns.inc
52
+ - ext/insns_ext/insns/2.0/insns_ext.c
53
+ - ext/insns_ext/insns/2.0/insns_info.inc
54
+ - ext/insns_ext/insns/2.0/vm_core_subset.h
48
55
  - flaw_detector.gemspec
49
56
  - lib/flaw_detector.rb
50
57
  - lib/flaw_detector/code_model/cfg_node.rb
@@ -54,39 +61,35 @@ files:
54
61
  - lib/flaw_detector/detector/abstract_detector.rb
55
62
  - lib/flaw_detector/detector/nil_false_path_flow.rb
56
63
  - lib/flaw_detector/formatter/csv_formatter.rb
64
+ - lib/flaw_detector/iseq/instruction_container.rb
57
65
  - lib/flaw_detector/message.rb
58
66
  - lib/flaw_detector/version.rb
59
67
  - sample/flaw_in_code.rb
60
68
  - spec/lib/flaw_detector_spec.rb
61
69
  - spec/spec_helper.rb
62
- homepage: ""
70
+ homepage: ''
63
71
  licenses: []
64
-
72
+ metadata: {}
65
73
  post_install_message:
66
74
  rdoc_options: []
67
-
68
- require_paths:
75
+ require_paths:
69
76
  - lib
70
- required_ruby_version: !ruby/object:Gem::Requirement
71
- none: false
72
- requirements:
73
- - - ~>
74
- - !ruby/object:Gem::Version
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '>'
80
+ - !ruby/object:Gem::Version
75
81
  version: 1.9.0
76
- required_rubygems_version: !ruby/object:Gem::Requirement
77
- none: false
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: "0"
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
82
87
  requirements: []
83
-
84
88
  rubyforge_project: flaw detector
85
- rubygems_version: 1.8.12
89
+ rubygems_version: 2.0.2
86
90
  signing_key:
87
- specification_version: 3
91
+ specification_version: 4
88
92
  summary: The tool to detect code's flaw with static analysis
89
- test_files:
93
+ test_files:
90
94
  - spec/lib/flaw_detector_spec.rb
91
95
  - spec/spec_helper.rb
92
- has_rdoc: