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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: af3e76154f18c212c10a2a6a3d4d107f64618255
|
4
|
+
data.tar.gz: 42d43bb6c926ad0ee08e07a4fda53b841613eef3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9bc4863341aeb50d5ee24209ae6997ab84ec155a9800d1adc5a150746e64f7cb12c5a0d962765526c3f833b808a940042377abbd835be22b3a78390392e0476e
|
7
|
+
data.tar.gz: 51a0e99b72ba5e61984856e288874431269ae84e32220f90bea7c843d44ab21d1a2c8ae74a487e276472ee2d5d0d7f93e470d93738101ba42425a3199ec7dd75
|
data/README.md
CHANGED
@@ -1,4 +1,64 @@
|
|
1
|
-
flaw_detector
|
1
|
+
FlawDetector [][Continuous Integration]
|
2
2
|
=============
|
3
|
+
FlawDetector is a tool to detect ruby code's flaw with static analysis.
|
4
|
+
In static analysis, it analyze RubyVM bytecode which is compiled from ruby code.
|
3
5
|
|
4
|
-
|
6
|
+
FlawDetector is similer to FindBugs which is a tool to detect java code's flaw.
|
7
|
+
For details of FindBugs, refer to references section in this text file.
|
8
|
+
|
9
|
+
[Continuous Integration]: http://travis-ci.org/ginriki/flaw_detector
|
10
|
+
|
11
|
+
Getting Started
|
12
|
+
-------
|
13
|
+
```shell
|
14
|
+
$ gem install flaw_detector
|
15
|
+
```
|
16
|
+
|
17
|
+
Usage
|
18
|
+
-------
|
19
|
+
```shell
|
20
|
+
flaw_detector [-f outfille] [--help] rbfile ...
|
21
|
+
```
|
22
|
+
|
23
|
+
Example
|
24
|
+
-------
|
25
|
+
```shell
|
26
|
+
$ flaw_detector -f result.csv sample/flaw_in_code.rb
|
27
|
+
```
|
28
|
+
|
29
|
+
Command Result
|
30
|
+
-------
|
31
|
+
Currently, FlawDetector supports only CSV format result.
|
32
|
+
Result example is as follows:
|
33
|
+
```file
|
34
|
+
$ cat result.csv
|
35
|
+
msgid,file,line,short_desc,long_desc,details
|
36
|
+
RCN_REDUNDANT_FALSECHECK_OF_FALSE_VALUE,sample/flaw_in_code.rb,4,Redundant falsecheck of value known to be false,Redundant falsecheck of a which is known to be false in LINE:2,This method contains a redundant check of a known false value against the constant false.
|
37
|
+
NP_ALWAYS_FALSE,sample/flaw_in_code.rb,7,False value missing method received,False value missing method received in a,"A false value, which is NilClass or FalseClass, is received missing method here. This will lead to a NoMethodError when the code is executed."
|
38
|
+
```
|
39
|
+
|
40
|
+
Each line represents a flaw.
|
41
|
+
If you want to know how flaw can be shown in result,
|
42
|
+
refer to [message.rb](https://github.com/ginriki/flaw_detector/blob/master/lib/flaw_detector/message.rb)
|
43
|
+
|
44
|
+
Fix and Recheck
|
45
|
+
------
|
46
|
+
According to the result, you should fix source code and recheck it by FlawDetector until "OK" is displaied
|
47
|
+
```file
|
48
|
+
$ emacs sample/flaw_in_code.rb
|
49
|
+
$ cat sample/flaw_in_code.rb
|
50
|
+
def no_flaw(a)
|
51
|
+
if a
|
52
|
+
rl = a + 1
|
53
|
+
else
|
54
|
+
rl = a.to_i + 1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
$ flaw_detector sample/flaw_in_code.rb
|
58
|
+
OK
|
59
|
+
$
|
60
|
+
```
|
61
|
+
|
62
|
+
References
|
63
|
+
------
|
64
|
+
* http://findbugs.sourceforge.net/findbugs2.html
|
data/ext/insns_ext/extconf.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
require 'mkmf'
|
2
|
-
create_makefile("insns_ext")
|
2
|
+
create_makefile("insns_ext", "insns/#{RUBY_VERSION[0..2]}")
|
data/ext/insns_ext/insn_ext.rb
CHANGED
@@ -3,5 +3,37 @@ module InsnExt
|
|
3
3
|
def insn_num(insn_name)
|
4
4
|
return RubyVM::INSTRUCTION_NAMES.index(insn_name.to_s)
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
|
+
# @todo refactoring from c-function to pure ruby function
|
8
|
+
alias :_insn_stack_increase :insn_stack_increase
|
9
|
+
|
10
|
+
if RUBY_VERSION =~ /^2.0/
|
11
|
+
VM_CALL_ARGS_BLOCKARG = (0x01 ** 2)
|
12
|
+
|
13
|
+
# Override for substitution of CALL_INFO cast
|
14
|
+
# in c-function@insns_info.inc
|
15
|
+
def insn_stack_increase(opcode_index, ary)
|
16
|
+
call_info = [:send, :invokesuper, :opt_send_simple, :invokeblock]
|
17
|
+
name = RubyVM::INSTRUCTION_NAMES[opcode_index].to_sym
|
18
|
+
unless call_info.include?(name)
|
19
|
+
return _insn_stack_increase(opcode_index, ary)
|
20
|
+
else
|
21
|
+
case name
|
22
|
+
when :opt_send_simple
|
23
|
+
inc = -ary[0][:orig_argc]
|
24
|
+
when :invokeblock
|
25
|
+
inc = 1-ary[0][:orig_argc]
|
26
|
+
when :send, :invokesuper
|
27
|
+
inc = -ary[0][:orig_argc]
|
28
|
+
inc += -1 if (ary[0][:flag] & VM_CALL_ARGS_BLOCKARG) != 0
|
29
|
+
else
|
30
|
+
raise "unknown state"
|
31
|
+
end
|
32
|
+
return inc
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
#don't need to override insn_stack_increase
|
37
|
+
end
|
38
|
+
module_function :insn_num, :insn_stack_increase, :_insn_stack_increase
|
7
39
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (C) 1993-2010 Yukihiro Matsumoto. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
16
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
17
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
18
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
19
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
20
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
21
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
22
|
+
SUCH DAMAGE.
|
File without changes
|
File without changes
|
@@ -9,18 +9,18 @@
|
|
9
9
|
or insns2vm.rb
|
10
10
|
*/
|
11
11
|
|
12
|
+
#define TS_ISEQ 'S'
|
13
|
+
#define TS_GENTRY 'G'
|
12
14
|
#define TS_OFFSET 'O'
|
13
|
-
#define TS_NUM 'N'
|
14
|
-
#define TS_LINDEX 'L'
|
15
15
|
#define TS_DINDEX 'D'
|
16
|
-
#define TS_VALUE 'V'
|
17
|
-
#define TS_ID 'I'
|
18
|
-
#define TS_GENTRY 'G'
|
19
|
-
#define TS_IC 'C'
|
20
|
-
#define TS_CDHASH 'H'
|
21
|
-
#define TS_ISEQ 'S'
|
22
16
|
#define TS_VARIABLE '.'
|
17
|
+
#define TS_CDHASH 'H'
|
18
|
+
#define TS_IC 'C'
|
19
|
+
#define TS_ID 'I'
|
23
20
|
#define TS_FUNCPTR 'F'
|
21
|
+
#define TS_VALUE 'V'
|
22
|
+
#define TS_LINDEX 'L'
|
23
|
+
#define TS_NUM 'N'
|
24
24
|
|
25
25
|
static const char *const insn_name_info[] = {
|
26
26
|
"nop",
|
@@ -110,8 +110,8 @@ static const char *const insn_operand_info[] = {
|
|
110
110
|
"",
|
111
111
|
"L",
|
112
112
|
"L",
|
113
|
-
"
|
114
|
-
"
|
113
|
+
"NN",
|
114
|
+
"N",
|
115
115
|
"DN",
|
116
116
|
"DN",
|
117
117
|
"IC",
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
16
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
17
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
18
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
19
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
20
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
21
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
22
|
+
SUCH DAMAGE.
|
@@ -0,0 +1,187 @@
|
|
1
|
+
/** -*-c-*-
|
2
|
+
This file contains YARV instructions list.
|
3
|
+
|
4
|
+
----
|
5
|
+
This file is auto generated by insns2vm.rb
|
6
|
+
DO NOT TOUCH!
|
7
|
+
|
8
|
+
If you want to fix something, you must edit 'template/insns.inc.tmpl'
|
9
|
+
or insns2vm.rb
|
10
|
+
*/
|
11
|
+
|
12
|
+
|
13
|
+
/* BIN : Basic Instruction Name */
|
14
|
+
#define BIN(n) YARVINSN_##n
|
15
|
+
|
16
|
+
enum ruby_vminsn_type {
|
17
|
+
BIN(nop) = 0,
|
18
|
+
|
19
|
+
BIN(getlocal) = 1,
|
20
|
+
|
21
|
+
BIN(setlocal) = 2,
|
22
|
+
|
23
|
+
BIN(getspecial) = 3,
|
24
|
+
|
25
|
+
BIN(setspecial) = 4,
|
26
|
+
|
27
|
+
BIN(getinstancevariable) = 5,
|
28
|
+
|
29
|
+
BIN(setinstancevariable) = 6,
|
30
|
+
|
31
|
+
BIN(getclassvariable) = 7,
|
32
|
+
|
33
|
+
BIN(setclassvariable) = 8,
|
34
|
+
|
35
|
+
BIN(getconstant) = 9,
|
36
|
+
|
37
|
+
BIN(setconstant) = 10,
|
38
|
+
|
39
|
+
BIN(getglobal) = 11,
|
40
|
+
|
41
|
+
BIN(setglobal) = 12,
|
42
|
+
|
43
|
+
BIN(putnil) = 13,
|
44
|
+
|
45
|
+
BIN(putself) = 14,
|
46
|
+
|
47
|
+
BIN(putobject) = 15,
|
48
|
+
|
49
|
+
BIN(putspecialobject) = 16,
|
50
|
+
|
51
|
+
BIN(putiseq) = 17,
|
52
|
+
|
53
|
+
BIN(putstring) = 18,
|
54
|
+
|
55
|
+
BIN(concatstrings) = 19,
|
56
|
+
|
57
|
+
BIN(tostring) = 20,
|
58
|
+
|
59
|
+
BIN(toregexp) = 21,
|
60
|
+
|
61
|
+
BIN(newarray) = 22,
|
62
|
+
|
63
|
+
BIN(duparray) = 23,
|
64
|
+
|
65
|
+
BIN(expandarray) = 24,
|
66
|
+
|
67
|
+
BIN(concatarray) = 25,
|
68
|
+
|
69
|
+
BIN(splatarray) = 26,
|
70
|
+
|
71
|
+
BIN(newhash) = 27,
|
72
|
+
|
73
|
+
BIN(newrange) = 28,
|
74
|
+
|
75
|
+
BIN(pop) = 29,
|
76
|
+
|
77
|
+
BIN(dup) = 30,
|
78
|
+
|
79
|
+
BIN(dupn) = 31,
|
80
|
+
|
81
|
+
BIN(swap) = 32,
|
82
|
+
|
83
|
+
BIN(reput) = 33,
|
84
|
+
|
85
|
+
BIN(topn) = 34,
|
86
|
+
|
87
|
+
BIN(setn) = 35,
|
88
|
+
|
89
|
+
BIN(adjuststack) = 36,
|
90
|
+
|
91
|
+
BIN(defined) = 37,
|
92
|
+
|
93
|
+
BIN(checkmatch) = 38,
|
94
|
+
|
95
|
+
BIN(trace) = 39,
|
96
|
+
|
97
|
+
BIN(defineclass) = 40,
|
98
|
+
|
99
|
+
BIN(send) = 41,
|
100
|
+
|
101
|
+
BIN(opt_send_simple) = 42,
|
102
|
+
|
103
|
+
BIN(invokesuper) = 43,
|
104
|
+
|
105
|
+
BIN(invokeblock) = 44,
|
106
|
+
|
107
|
+
BIN(leave) = 45,
|
108
|
+
|
109
|
+
BIN(throw) = 46,
|
110
|
+
|
111
|
+
BIN(jump) = 47,
|
112
|
+
|
113
|
+
BIN(branchif) = 48,
|
114
|
+
|
115
|
+
BIN(branchunless) = 49,
|
116
|
+
|
117
|
+
BIN(getinlinecache) = 50,
|
118
|
+
|
119
|
+
BIN(onceinlinecache) = 51,
|
120
|
+
|
121
|
+
BIN(setinlinecache) = 52,
|
122
|
+
|
123
|
+
BIN(opt_case_dispatch) = 53,
|
124
|
+
|
125
|
+
BIN(opt_plus) = 54,
|
126
|
+
|
127
|
+
BIN(opt_minus) = 55,
|
128
|
+
|
129
|
+
BIN(opt_mult) = 56,
|
130
|
+
|
131
|
+
BIN(opt_div) = 57,
|
132
|
+
|
133
|
+
BIN(opt_mod) = 58,
|
134
|
+
|
135
|
+
BIN(opt_eq) = 59,
|
136
|
+
|
137
|
+
BIN(opt_neq) = 60,
|
138
|
+
|
139
|
+
BIN(opt_lt) = 61,
|
140
|
+
|
141
|
+
BIN(opt_le) = 62,
|
142
|
+
|
143
|
+
BIN(opt_gt) = 63,
|
144
|
+
|
145
|
+
BIN(opt_ge) = 64,
|
146
|
+
|
147
|
+
BIN(opt_ltlt) = 65,
|
148
|
+
|
149
|
+
BIN(opt_aref) = 66,
|
150
|
+
|
151
|
+
BIN(opt_aset) = 67,
|
152
|
+
|
153
|
+
BIN(opt_length) = 68,
|
154
|
+
|
155
|
+
BIN(opt_size) = 69,
|
156
|
+
|
157
|
+
BIN(opt_empty_p) = 70,
|
158
|
+
|
159
|
+
BIN(opt_succ) = 71,
|
160
|
+
|
161
|
+
BIN(opt_not) = 72,
|
162
|
+
|
163
|
+
BIN(opt_regexpmatch1) = 73,
|
164
|
+
|
165
|
+
BIN(opt_regexpmatch2) = 74,
|
166
|
+
|
167
|
+
BIN(opt_call_c_function) = 75,
|
168
|
+
|
169
|
+
BIN(bitblt) = 76,
|
170
|
+
|
171
|
+
BIN(answer) = 77,
|
172
|
+
|
173
|
+
BIN(getlocal_OP__WC__0) = 78,
|
174
|
+
|
175
|
+
BIN(getlocal_OP__WC__1) = 79,
|
176
|
+
|
177
|
+
BIN(setlocal_OP__WC__0) = 80,
|
178
|
+
|
179
|
+
BIN(setlocal_OP__WC__1) = 81,
|
180
|
+
|
181
|
+
BIN(putobject_OP_INT2FIX_O_0_C_) = 82,
|
182
|
+
|
183
|
+
BIN(putobject_OP_INT2FIX_O_1_C_) = 83,
|
184
|
+
|
185
|
+
VM_INSTRUCTION_SIZE = 84
|
186
|
+
};
|
187
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#define USE_INSN_STACK_INCREASE
|
2
|
+
#define USE_INSN_RET_NUM
|
3
|
+
#include "ruby.h"
|
4
|
+
|
5
|
+
#include "vm_core_subset.h"
|
6
|
+
#include "insns.inc"
|
7
|
+
#include "insns_info.inc"
|
8
|
+
|
9
|
+
VALUE wrap_insn_len(VALUE self, VALUE insn)
|
10
|
+
{
|
11
|
+
int len = insn_len(FIX2INT(insn));
|
12
|
+
return INT2FIX(len);
|
13
|
+
}
|
14
|
+
|
15
|
+
VALUE wrap_insn_stack_increase(VALUE self, VALUE insn, VALUE ope_ary)
|
16
|
+
{
|
17
|
+
int inc = insn_stack_increase(0, FIX2INT(insn), RARRAY_PTR(ope_ary));
|
18
|
+
return INT2FIX(inc);
|
19
|
+
}
|
20
|
+
|
21
|
+
VALUE wrap_insn_ret_num(VALUE self, VALUE insn)
|
22
|
+
{
|
23
|
+
int ret_num = insn_ret_num(FIX2INT(insn));
|
24
|
+
return INT2FIX(ret_num);
|
25
|
+
}
|
26
|
+
|
27
|
+
void Init_insns_ext()
|
28
|
+
{
|
29
|
+
VALUE module;
|
30
|
+
|
31
|
+
module = rb_define_module("InsnExt");
|
32
|
+
rb_define_module_function(module, "insn_len", wrap_insn_len, 1);
|
33
|
+
rb_define_module_function(module, "insn_stack_increase", wrap_insn_stack_increase, 2);
|
34
|
+
rb_define_module_function(module, "insn_ret_num", wrap_insn_ret_num, 1);
|
35
|
+
}
|
36
|
+
|
@@ -0,0 +1,724 @@
|
|
1
|
+
/** -*-c-*-
|
2
|
+
This file contains instruction information for yarv instruction sequence.
|
3
|
+
|
4
|
+
----
|
5
|
+
This file is auto generated by insns2vm.rb
|
6
|
+
DO NOT TOUCH!
|
7
|
+
|
8
|
+
If you want to fix something, you must edit 'template/insns_info.inc.tmpl'
|
9
|
+
or insns2vm.rb
|
10
|
+
*/
|
11
|
+
|
12
|
+
#define TS_ISEQ 'S'
|
13
|
+
#define TS_GENTRY 'G'
|
14
|
+
#define TS_OFFSET 'O'
|
15
|
+
#define TS_CALLINFO 'C'
|
16
|
+
#define TS_VARIABLE '.'
|
17
|
+
#define TS_CDHASH 'H'
|
18
|
+
#define TS_IC 'K'
|
19
|
+
#define TS_ID 'I'
|
20
|
+
#define TS_FUNCPTR 'F'
|
21
|
+
#define TS_VALUE 'V'
|
22
|
+
#define TS_LINDEX 'L'
|
23
|
+
#define TS_NUM 'N'
|
24
|
+
|
25
|
+
static const char *const insn_name_info[] = {
|
26
|
+
"nop",
|
27
|
+
"getlocal",
|
28
|
+
"setlocal",
|
29
|
+
"getspecial",
|
30
|
+
"setspecial",
|
31
|
+
"getinstancevariable",
|
32
|
+
"setinstancevariable",
|
33
|
+
"getclassvariable",
|
34
|
+
"setclassvariable",
|
35
|
+
"getconstant",
|
36
|
+
"setconstant",
|
37
|
+
"getglobal",
|
38
|
+
"setglobal",
|
39
|
+
"putnil",
|
40
|
+
"putself",
|
41
|
+
"putobject",
|
42
|
+
"putspecialobject",
|
43
|
+
"putiseq",
|
44
|
+
"putstring",
|
45
|
+
"concatstrings",
|
46
|
+
"tostring",
|
47
|
+
"toregexp",
|
48
|
+
"newarray",
|
49
|
+
"duparray",
|
50
|
+
"expandarray",
|
51
|
+
"concatarray",
|
52
|
+
"splatarray",
|
53
|
+
"newhash",
|
54
|
+
"newrange",
|
55
|
+
"pop",
|
56
|
+
"dup",
|
57
|
+
"dupn",
|
58
|
+
"swap",
|
59
|
+
"reput",
|
60
|
+
"topn",
|
61
|
+
"setn",
|
62
|
+
"adjuststack",
|
63
|
+
"defined",
|
64
|
+
"checkmatch",
|
65
|
+
"trace",
|
66
|
+
"defineclass",
|
67
|
+
"send",
|
68
|
+
"opt_send_simple",
|
69
|
+
"invokesuper",
|
70
|
+
"invokeblock",
|
71
|
+
"leave",
|
72
|
+
"throw",
|
73
|
+
"jump",
|
74
|
+
"branchif",
|
75
|
+
"branchunless",
|
76
|
+
"getinlinecache",
|
77
|
+
"onceinlinecache",
|
78
|
+
"setinlinecache",
|
79
|
+
"opt_case_dispatch",
|
80
|
+
"opt_plus",
|
81
|
+
"opt_minus",
|
82
|
+
"opt_mult",
|
83
|
+
"opt_div",
|
84
|
+
"opt_mod",
|
85
|
+
"opt_eq",
|
86
|
+
"opt_neq",
|
87
|
+
"opt_lt",
|
88
|
+
"opt_le",
|
89
|
+
"opt_gt",
|
90
|
+
"opt_ge",
|
91
|
+
"opt_ltlt",
|
92
|
+
"opt_aref",
|
93
|
+
"opt_aset",
|
94
|
+
"opt_length",
|
95
|
+
"opt_size",
|
96
|
+
"opt_empty_p",
|
97
|
+
"opt_succ",
|
98
|
+
"opt_not",
|
99
|
+
"opt_regexpmatch1",
|
100
|
+
"opt_regexpmatch2",
|
101
|
+
"opt_call_c_function",
|
102
|
+
"bitblt",
|
103
|
+
"answer",
|
104
|
+
"getlocal_OP__WC__0",
|
105
|
+
"getlocal_OP__WC__1",
|
106
|
+
"setlocal_OP__WC__0",
|
107
|
+
"setlocal_OP__WC__1",
|
108
|
+
"putobject_OP_INT2FIX_O_0_C_",
|
109
|
+
"putobject_OP_INT2FIX_O_1_C_",
|
110
|
+
|
111
|
+
};
|
112
|
+
|
113
|
+
static const char *const insn_operand_info[] = {
|
114
|
+
"",
|
115
|
+
"LN",
|
116
|
+
"LN",
|
117
|
+
"NN",
|
118
|
+
"N",
|
119
|
+
"IK",
|
120
|
+
"IK",
|
121
|
+
"I",
|
122
|
+
"I",
|
123
|
+
"I",
|
124
|
+
"I",
|
125
|
+
"G",
|
126
|
+
"G",
|
127
|
+
"",
|
128
|
+
"",
|
129
|
+
"V",
|
130
|
+
"N",
|
131
|
+
"S",
|
132
|
+
"V",
|
133
|
+
"N",
|
134
|
+
"",
|
135
|
+
"NN",
|
136
|
+
"N",
|
137
|
+
"V",
|
138
|
+
"NN",
|
139
|
+
"",
|
140
|
+
"V",
|
141
|
+
"N",
|
142
|
+
"N",
|
143
|
+
"",
|
144
|
+
"",
|
145
|
+
"N",
|
146
|
+
"",
|
147
|
+
"",
|
148
|
+
"N",
|
149
|
+
"N",
|
150
|
+
"N",
|
151
|
+
"NVV",
|
152
|
+
"N",
|
153
|
+
"N",
|
154
|
+
"ISN",
|
155
|
+
"C",
|
156
|
+
"C",
|
157
|
+
"C",
|
158
|
+
"C",
|
159
|
+
"",
|
160
|
+
"N",
|
161
|
+
"O",
|
162
|
+
"O",
|
163
|
+
"O",
|
164
|
+
"OK",
|
165
|
+
"OK",
|
166
|
+
"K",
|
167
|
+
"HO",
|
168
|
+
"C",
|
169
|
+
"C",
|
170
|
+
"C",
|
171
|
+
"C",
|
172
|
+
"C",
|
173
|
+
"C",
|
174
|
+
"CC",
|
175
|
+
"C",
|
176
|
+
"C",
|
177
|
+
"C",
|
178
|
+
"C",
|
179
|
+
"C",
|
180
|
+
"C",
|
181
|
+
"C",
|
182
|
+
"C",
|
183
|
+
"C",
|
184
|
+
"C",
|
185
|
+
"C",
|
186
|
+
"C",
|
187
|
+
"V",
|
188
|
+
"",
|
189
|
+
"F",
|
190
|
+
"",
|
191
|
+
"",
|
192
|
+
"L",
|
193
|
+
"L",
|
194
|
+
"L",
|
195
|
+
"L",
|
196
|
+
"",
|
197
|
+
"",
|
198
|
+
|
199
|
+
};
|
200
|
+
|
201
|
+
static const int insn_len_info[] = {
|
202
|
+
1,
|
203
|
+
3,
|
204
|
+
3,
|
205
|
+
3,
|
206
|
+
2,
|
207
|
+
3,
|
208
|
+
3,
|
209
|
+
2,
|
210
|
+
2,
|
211
|
+
2,
|
212
|
+
2,
|
213
|
+
2,
|
214
|
+
2,
|
215
|
+
1,
|
216
|
+
1,
|
217
|
+
2,
|
218
|
+
2,
|
219
|
+
2,
|
220
|
+
2,
|
221
|
+
2,
|
222
|
+
1,
|
223
|
+
3,
|
224
|
+
2,
|
225
|
+
2,
|
226
|
+
3,
|
227
|
+
1,
|
228
|
+
2,
|
229
|
+
2,
|
230
|
+
2,
|
231
|
+
1,
|
232
|
+
1,
|
233
|
+
2,
|
234
|
+
1,
|
235
|
+
1,
|
236
|
+
2,
|
237
|
+
2,
|
238
|
+
2,
|
239
|
+
4,
|
240
|
+
2,
|
241
|
+
2,
|
242
|
+
4,
|
243
|
+
2,
|
244
|
+
2,
|
245
|
+
2,
|
246
|
+
2,
|
247
|
+
1,
|
248
|
+
2,
|
249
|
+
2,
|
250
|
+
2,
|
251
|
+
2,
|
252
|
+
3,
|
253
|
+
3,
|
254
|
+
2,
|
255
|
+
3,
|
256
|
+
2,
|
257
|
+
2,
|
258
|
+
2,
|
259
|
+
2,
|
260
|
+
2,
|
261
|
+
2,
|
262
|
+
3,
|
263
|
+
2,
|
264
|
+
2,
|
265
|
+
2,
|
266
|
+
2,
|
267
|
+
2,
|
268
|
+
2,
|
269
|
+
2,
|
270
|
+
2,
|
271
|
+
2,
|
272
|
+
2,
|
273
|
+
2,
|
274
|
+
2,
|
275
|
+
2,
|
276
|
+
1,
|
277
|
+
2,
|
278
|
+
1,
|
279
|
+
1,
|
280
|
+
2,
|
281
|
+
2,
|
282
|
+
2,
|
283
|
+
2,
|
284
|
+
1,
|
285
|
+
1,
|
286
|
+
|
287
|
+
};
|
288
|
+
|
289
|
+
#ifdef USE_INSN_RET_NUM
|
290
|
+
static const int insn_stack_push_num_info[] = {
|
291
|
+
0,
|
292
|
+
1,
|
293
|
+
0,
|
294
|
+
1,
|
295
|
+
0,
|
296
|
+
1,
|
297
|
+
0,
|
298
|
+
1,
|
299
|
+
0,
|
300
|
+
1,
|
301
|
+
0,
|
302
|
+
1,
|
303
|
+
0,
|
304
|
+
1,
|
305
|
+
1,
|
306
|
+
1,
|
307
|
+
1,
|
308
|
+
1,
|
309
|
+
1,
|
310
|
+
1,
|
311
|
+
1,
|
312
|
+
1,
|
313
|
+
1,
|
314
|
+
1,
|
315
|
+
1,
|
316
|
+
1,
|
317
|
+
1,
|
318
|
+
1,
|
319
|
+
1,
|
320
|
+
0,
|
321
|
+
2,
|
322
|
+
1,
|
323
|
+
2,
|
324
|
+
1,
|
325
|
+
1,
|
326
|
+
1,
|
327
|
+
1,
|
328
|
+
1,
|
329
|
+
1,
|
330
|
+
0,
|
331
|
+
1,
|
332
|
+
1,
|
333
|
+
1,
|
334
|
+
1,
|
335
|
+
1,
|
336
|
+
1,
|
337
|
+
1,
|
338
|
+
0,
|
339
|
+
0,
|
340
|
+
0,
|
341
|
+
1,
|
342
|
+
1,
|
343
|
+
1,
|
344
|
+
0,
|
345
|
+
1,
|
346
|
+
1,
|
347
|
+
1,
|
348
|
+
1,
|
349
|
+
1,
|
350
|
+
1,
|
351
|
+
1,
|
352
|
+
1,
|
353
|
+
1,
|
354
|
+
1,
|
355
|
+
1,
|
356
|
+
1,
|
357
|
+
1,
|
358
|
+
1,
|
359
|
+
1,
|
360
|
+
1,
|
361
|
+
1,
|
362
|
+
1,
|
363
|
+
1,
|
364
|
+
1,
|
365
|
+
1,
|
366
|
+
0,
|
367
|
+
1,
|
368
|
+
1,
|
369
|
+
1,
|
370
|
+
1,
|
371
|
+
0,
|
372
|
+
0,
|
373
|
+
1,
|
374
|
+
1,
|
375
|
+
|
376
|
+
};
|
377
|
+
#endif
|
378
|
+
|
379
|
+
#ifdef USE_INSN_STACK_INCREASE
|
380
|
+
static int
|
381
|
+
insn_stack_increase(int depth, int insn, VALUE *opes)
|
382
|
+
{
|
383
|
+
switch(insn){
|
384
|
+
case BIN(nop):{
|
385
|
+
return depth + 0;
|
386
|
+
}
|
387
|
+
case BIN(getlocal):{
|
388
|
+
return depth + 1;
|
389
|
+
}
|
390
|
+
case BIN(setlocal):{
|
391
|
+
return depth + -1;
|
392
|
+
}
|
393
|
+
case BIN(getspecial):{
|
394
|
+
return depth + 1;
|
395
|
+
}
|
396
|
+
case BIN(setspecial):{
|
397
|
+
return depth + -1;
|
398
|
+
}
|
399
|
+
case BIN(getinstancevariable):{
|
400
|
+
return depth + 1;
|
401
|
+
}
|
402
|
+
case BIN(setinstancevariable):{
|
403
|
+
return depth + -1;
|
404
|
+
}
|
405
|
+
case BIN(getclassvariable):{
|
406
|
+
return depth + 1;
|
407
|
+
}
|
408
|
+
case BIN(setclassvariable):{
|
409
|
+
return depth + -1;
|
410
|
+
}
|
411
|
+
case BIN(getconstant):{
|
412
|
+
return depth + 0;
|
413
|
+
}
|
414
|
+
case BIN(setconstant):{
|
415
|
+
return depth + -2;
|
416
|
+
}
|
417
|
+
case BIN(getglobal):{
|
418
|
+
return depth + 1;
|
419
|
+
}
|
420
|
+
case BIN(setglobal):{
|
421
|
+
return depth + -1;
|
422
|
+
}
|
423
|
+
case BIN(putnil):{
|
424
|
+
return depth + 1;
|
425
|
+
}
|
426
|
+
case BIN(putself):{
|
427
|
+
return depth + 1;
|
428
|
+
}
|
429
|
+
case BIN(putobject):{
|
430
|
+
return depth + 1;
|
431
|
+
}
|
432
|
+
case BIN(putspecialobject):{
|
433
|
+
return depth + 1;
|
434
|
+
}
|
435
|
+
case BIN(putiseq):{
|
436
|
+
return depth + 1;
|
437
|
+
}
|
438
|
+
case BIN(putstring):{
|
439
|
+
return depth + 1;
|
440
|
+
}
|
441
|
+
case BIN(concatstrings):{
|
442
|
+
int inc = 0;
|
443
|
+
int num = FIX2INT(opes[0]);
|
444
|
+
inc += 1 - num;;
|
445
|
+
return depth + inc;
|
446
|
+
}
|
447
|
+
case BIN(tostring):{
|
448
|
+
return depth + 0;
|
449
|
+
}
|
450
|
+
case BIN(toregexp):{
|
451
|
+
int inc = 0;
|
452
|
+
int cnt = FIX2INT(opes[1]);
|
453
|
+
inc += 1 - cnt;;
|
454
|
+
return depth + inc;
|
455
|
+
}
|
456
|
+
case BIN(newarray):{
|
457
|
+
int inc = 0;
|
458
|
+
int num = FIX2INT(opes[0]);
|
459
|
+
inc += 1 - num;;
|
460
|
+
return depth + inc;
|
461
|
+
}
|
462
|
+
case BIN(duparray):{
|
463
|
+
return depth + 1;
|
464
|
+
}
|
465
|
+
case BIN(expandarray):{
|
466
|
+
int inc = 0;
|
467
|
+
int num = FIX2INT(opes[0]);
|
468
|
+
int flag = FIX2INT(opes[1]);
|
469
|
+
inc += num - 1 + (flag & 1 ? 1 : 0);;
|
470
|
+
return depth + inc;
|
471
|
+
}
|
472
|
+
case BIN(concatarray):{
|
473
|
+
return depth + -1;
|
474
|
+
}
|
475
|
+
case BIN(splatarray):{
|
476
|
+
return depth + 0;
|
477
|
+
}
|
478
|
+
case BIN(newhash):{
|
479
|
+
int inc = 0;
|
480
|
+
int num = FIX2INT(opes[0]);
|
481
|
+
inc += 1 - num;;
|
482
|
+
return depth + inc;
|
483
|
+
}
|
484
|
+
case BIN(newrange):{
|
485
|
+
return depth + -1;
|
486
|
+
}
|
487
|
+
case BIN(pop):{
|
488
|
+
return depth + -1;
|
489
|
+
}
|
490
|
+
case BIN(dup):{
|
491
|
+
return depth + 1;
|
492
|
+
}
|
493
|
+
case BIN(dupn):{
|
494
|
+
int inc = 0;
|
495
|
+
int n = FIX2INT(opes[0]);
|
496
|
+
inc += n;;
|
497
|
+
return depth + inc;
|
498
|
+
}
|
499
|
+
case BIN(swap):{
|
500
|
+
return depth + 0;
|
501
|
+
}
|
502
|
+
case BIN(reput):{
|
503
|
+
int inc = 0;
|
504
|
+
inc += 0;;
|
505
|
+
return depth + inc;
|
506
|
+
}
|
507
|
+
case BIN(topn):{
|
508
|
+
int inc = 0;
|
509
|
+
inc += 1;;
|
510
|
+
return depth + inc;
|
511
|
+
}
|
512
|
+
case BIN(setn):{
|
513
|
+
int inc = 0;
|
514
|
+
inc += 0;
|
515
|
+
return depth + inc;
|
516
|
+
}
|
517
|
+
case BIN(adjuststack):{
|
518
|
+
int inc = 0;
|
519
|
+
int n = FIX2INT(opes[0]);
|
520
|
+
inc -= n;
|
521
|
+
return depth + inc;
|
522
|
+
}
|
523
|
+
case BIN(defined):{
|
524
|
+
return depth + 0;
|
525
|
+
}
|
526
|
+
case BIN(checkmatch):{
|
527
|
+
return depth + -1;
|
528
|
+
}
|
529
|
+
case BIN(trace):{
|
530
|
+
return depth + 0;
|
531
|
+
}
|
532
|
+
case BIN(defineclass):{
|
533
|
+
return depth + -1;
|
534
|
+
}
|
535
|
+
case BIN(send):{
|
536
|
+
int inc = 0;
|
537
|
+
CALL_INFO ci = (CALL_INFO)(opes[0]);
|
538
|
+
inc += - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0));;
|
539
|
+
return depth + inc;
|
540
|
+
}
|
541
|
+
case BIN(opt_send_simple):{
|
542
|
+
int inc = 0;
|
543
|
+
CALL_INFO ci = (CALL_INFO)(opes[0]);
|
544
|
+
inc += -ci->orig_argc;;
|
545
|
+
return depth + inc;
|
546
|
+
}
|
547
|
+
case BIN(invokesuper):{
|
548
|
+
int inc = 0;
|
549
|
+
CALL_INFO ci = (CALL_INFO)(opes[0]);
|
550
|
+
inc += - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0));;
|
551
|
+
return depth + inc;
|
552
|
+
}
|
553
|
+
case BIN(invokeblock):{
|
554
|
+
int inc = 0;
|
555
|
+
CALL_INFO ci = (CALL_INFO)(opes[0]);
|
556
|
+
inc += 1 - ci->orig_argc;;
|
557
|
+
return depth + inc;
|
558
|
+
}
|
559
|
+
case BIN(leave):{
|
560
|
+
return depth + 0;
|
561
|
+
}
|
562
|
+
case BIN(throw):{
|
563
|
+
return depth + 0;
|
564
|
+
}
|
565
|
+
case BIN(jump):{
|
566
|
+
return depth + 0;
|
567
|
+
}
|
568
|
+
case BIN(branchif):{
|
569
|
+
return depth + -1;
|
570
|
+
}
|
571
|
+
case BIN(branchunless):{
|
572
|
+
return depth + -1;
|
573
|
+
}
|
574
|
+
case BIN(getinlinecache):{
|
575
|
+
return depth + 1;
|
576
|
+
}
|
577
|
+
case BIN(onceinlinecache):{
|
578
|
+
return depth + 1;
|
579
|
+
}
|
580
|
+
case BIN(setinlinecache):{
|
581
|
+
return depth + 0;
|
582
|
+
}
|
583
|
+
case BIN(opt_case_dispatch):{
|
584
|
+
int inc = 0;
|
585
|
+
inc += -1;;
|
586
|
+
return depth + inc;
|
587
|
+
}
|
588
|
+
case BIN(opt_plus):{
|
589
|
+
return depth + -1;
|
590
|
+
}
|
591
|
+
case BIN(opt_minus):{
|
592
|
+
return depth + -1;
|
593
|
+
}
|
594
|
+
case BIN(opt_mult):{
|
595
|
+
return depth + -1;
|
596
|
+
}
|
597
|
+
case BIN(opt_div):{
|
598
|
+
return depth + -1;
|
599
|
+
}
|
600
|
+
case BIN(opt_mod):{
|
601
|
+
return depth + -1;
|
602
|
+
}
|
603
|
+
case BIN(opt_eq):{
|
604
|
+
return depth + -1;
|
605
|
+
}
|
606
|
+
case BIN(opt_neq):{
|
607
|
+
return depth + -1;
|
608
|
+
}
|
609
|
+
case BIN(opt_lt):{
|
610
|
+
return depth + -1;
|
611
|
+
}
|
612
|
+
case BIN(opt_le):{
|
613
|
+
return depth + -1;
|
614
|
+
}
|
615
|
+
case BIN(opt_gt):{
|
616
|
+
return depth + -1;
|
617
|
+
}
|
618
|
+
case BIN(opt_ge):{
|
619
|
+
return depth + -1;
|
620
|
+
}
|
621
|
+
case BIN(opt_ltlt):{
|
622
|
+
return depth + -1;
|
623
|
+
}
|
624
|
+
case BIN(opt_aref):{
|
625
|
+
return depth + -1;
|
626
|
+
}
|
627
|
+
case BIN(opt_aset):{
|
628
|
+
return depth + -2;
|
629
|
+
}
|
630
|
+
case BIN(opt_length):{
|
631
|
+
return depth + 0;
|
632
|
+
}
|
633
|
+
case BIN(opt_size):{
|
634
|
+
return depth + 0;
|
635
|
+
}
|
636
|
+
case BIN(opt_empty_p):{
|
637
|
+
return depth + 0;
|
638
|
+
}
|
639
|
+
case BIN(opt_succ):{
|
640
|
+
return depth + 0;
|
641
|
+
}
|
642
|
+
case BIN(opt_not):{
|
643
|
+
return depth + 0;
|
644
|
+
}
|
645
|
+
case BIN(opt_regexpmatch1):{
|
646
|
+
return depth + 0;
|
647
|
+
}
|
648
|
+
case BIN(opt_regexpmatch2):{
|
649
|
+
return depth + -1;
|
650
|
+
}
|
651
|
+
case BIN(opt_call_c_function):{
|
652
|
+
return depth + 0;
|
653
|
+
}
|
654
|
+
case BIN(bitblt):{
|
655
|
+
return depth + 1;
|
656
|
+
}
|
657
|
+
case BIN(answer):{
|
658
|
+
return depth + 1;
|
659
|
+
}
|
660
|
+
case BIN(getlocal_OP__WC__0):{
|
661
|
+
return depth + 1;
|
662
|
+
}
|
663
|
+
case BIN(getlocal_OP__WC__1):{
|
664
|
+
return depth + 1;
|
665
|
+
}
|
666
|
+
case BIN(setlocal_OP__WC__0):{
|
667
|
+
return depth + -1;
|
668
|
+
}
|
669
|
+
case BIN(setlocal_OP__WC__1):{
|
670
|
+
return depth + -1;
|
671
|
+
}
|
672
|
+
case BIN(putobject_OP_INT2FIX_O_0_C_):{
|
673
|
+
return depth + 1;
|
674
|
+
}
|
675
|
+
case BIN(putobject_OP_INT2FIX_O_1_C_):{
|
676
|
+
return depth + 1;
|
677
|
+
}
|
678
|
+
|
679
|
+
default:
|
680
|
+
rb_bug("insn_sp_increase: unreachable");
|
681
|
+
}
|
682
|
+
return 0;
|
683
|
+
}
|
684
|
+
#endif
|
685
|
+
|
686
|
+
/* some utilities */
|
687
|
+
|
688
|
+
static int
|
689
|
+
insn_len(VALUE insn)
|
690
|
+
{
|
691
|
+
return insn_len_info[(int)insn];
|
692
|
+
}
|
693
|
+
|
694
|
+
static const char *
|
695
|
+
insn_name(VALUE insn)
|
696
|
+
{
|
697
|
+
return insn_name_info[(int)insn];
|
698
|
+
}
|
699
|
+
|
700
|
+
static const char *
|
701
|
+
insn_op_types(VALUE insn)
|
702
|
+
{
|
703
|
+
return insn_operand_info[(int)insn];
|
704
|
+
}
|
705
|
+
|
706
|
+
static int
|
707
|
+
insn_op_type(VALUE insn, long pos)
|
708
|
+
{
|
709
|
+
int len = insn_len(insn) - 1;
|
710
|
+
if(pos < len){
|
711
|
+
return insn_operand_info[(int)insn][pos];
|
712
|
+
}
|
713
|
+
else{
|
714
|
+
return 0;
|
715
|
+
}
|
716
|
+
}
|
717
|
+
|
718
|
+
#ifdef USE_INSN_RET_NUM
|
719
|
+
static int
|
720
|
+
insn_ret_num(VALUE insn)
|
721
|
+
{
|
722
|
+
return insn_stack_push_num_info[(int)insn];
|
723
|
+
}
|
724
|
+
#endif
|