flaw_detector 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +62 -2
- data/ext/insns_ext/extconf.rb +1 -1
- data/ext/insns_ext/insn_ext.rb +33 -1
- data/ext/insns_ext/insns/1.9/BSDL +22 -0
- data/ext/insns_ext/{insns.inc → insns/1.9/insns.inc} +0 -0
- data/ext/insns_ext/{insns_ext.c → insns/1.9/insns_ext.c} +0 -0
- data/ext/insns_ext/{insns_info.inc → insns/1.9/insns_info.inc} +10 -10
- data/ext/insns_ext/insns/2.0/BSDL +22 -0
- data/ext/insns_ext/insns/2.0/insns.inc +187 -0
- data/ext/insns_ext/insns/2.0/insns_ext.c +36 -0
- data/ext/insns_ext/insns/2.0/insns_info.inc +724 -0
- data/ext/insns_ext/insns/2.0/vm_core_subset.h +43 -0
- data/flaw_detector.gemspec +2 -2
- data/lib/flaw_detector.rb +15 -7
- data/lib/flaw_detector/detector/nil_false_path_flow.rb +9 -7
- data/lib/flaw_detector/iseq/instruction_container.rb +83 -0
- data/lib/flaw_detector/message.rb +3 -3
- data/lib/flaw_detector/version.rb +1 -1
- metadata +49 -46
@@ -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 */
|
data/flaw_detector.gemspec
CHANGED
@@ -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
|
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 = "
|
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
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
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[
|
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[
|
51
|
-
klass = RCEV_KLASS_OF_METHODS[obj_insn[
|
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
|
-
#
|
124
|
-
# return
|
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[
|
151
|
-
|
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
|
15
|
-
:long_desc => "Redundant falsecheck of %{0} which is known to be
|
16
|
-
:details => "This method contains a redundant check of a
|
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",
|
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
|
-
|
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
|
-
|
14
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
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.
|
46
|
-
- ext/insns_ext/
|
47
|
-
- ext/insns_ext/
|
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
|
-
|
72
|
-
|
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
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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:
|
89
|
+
rubygems_version: 2.0.2
|
86
90
|
signing_key:
|
87
|
-
specification_version:
|
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:
|