thrift 0.23.0 → 0.25.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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +203 -40
  3. data/ext/binary_protocol_accelerated.c +130 -40
  4. data/ext/bytes.c +14 -0
  5. data/ext/compact_protocol.c +184 -91
  6. data/ext/constants.h +3 -0
  7. data/ext/extconf.rb +12 -4
  8. data/ext/macros.h +11 -0
  9. data/ext/memory_buffer.c +67 -12
  10. data/ext/struct.c +192 -71
  11. data/ext/thrift_native.c +7 -0
  12. data/lib/thrift/bytes.rb +6 -3
  13. data/lib/thrift/client.rb +31 -33
  14. data/lib/thrift/exceptions.rb +11 -8
  15. data/lib/thrift/multiplexed_processor.rb +17 -8
  16. data/lib/thrift/processor.rb +25 -3
  17. data/lib/thrift/protocol/base_protocol.rb +66 -31
  18. data/lib/thrift/protocol/binary_protocol.rb +80 -37
  19. data/lib/thrift/protocol/binary_protocol_accelerated.rb +7 -2
  20. data/lib/thrift/protocol/compact_protocol.rb +204 -88
  21. data/lib/thrift/protocol/header_protocol.rb +15 -3
  22. data/lib/thrift/protocol/json_protocol.rb +158 -109
  23. data/lib/thrift/protocol/multiplexed_protocol.rb +3 -3
  24. data/lib/thrift/protocol/protocol_decorator.rb +6 -2
  25. data/lib/thrift/serializer/deserializer.rb +1 -0
  26. data/lib/thrift/serializer/serializer.rb +7 -0
  27. data/lib/thrift/server/base_server.rb +11 -2
  28. data/lib/thrift/server/nonblocking_server.rb +69 -20
  29. data/lib/thrift/server/rack_application.rb +69 -0
  30. data/lib/thrift/server/simple_server.rb +27 -15
  31. data/lib/thrift/server/thin_http_server.rb +21 -44
  32. data/lib/thrift/server/thread_pool_server.rb +21 -17
  33. data/lib/thrift/server/threaded_server.rb +22 -18
  34. data/lib/thrift/struct.rb +34 -18
  35. data/lib/thrift/struct_union.rb +37 -36
  36. data/lib/thrift/thrift_native.rb +2 -1
  37. data/lib/thrift/transport/base_server_transport.rb +3 -0
  38. data/lib/thrift/transport/base_transport.rb +26 -4
  39. data/lib/thrift/transport/buffered_transport.rb +5 -4
  40. data/lib/thrift/transport/framed_transport.rb +33 -7
  41. data/lib/thrift/transport/header_transport.rb +159 -33
  42. data/lib/thrift/transport/http_client_transport.rb +28 -14
  43. data/lib/thrift/transport/io_stream_transport.rb +3 -1
  44. data/lib/thrift/transport/memory_buffer_transport.rb +14 -9
  45. data/lib/thrift/transport/server_socket.rb +10 -8
  46. data/lib/thrift/transport/socket.rb +85 -48
  47. data/lib/thrift/transport/ssl_server_socket.rb +67 -6
  48. data/lib/thrift/transport/ssl_socket.rb +73 -14
  49. data/lib/thrift/transport/unix_server_socket.rb +6 -2
  50. data/lib/thrift/transport/unix_socket.rb +5 -6
  51. data/lib/thrift/types.rb +23 -22
  52. data/lib/thrift/union.rb +21 -11
  53. data/lib/thrift/uuid.rb +9 -8
  54. data/lib/thrift.rb +40 -39
  55. metadata +7 -266
  56. data/benchmark/Benchmark.thrift +0 -24
  57. data/benchmark/benchmark.rb +0 -285
  58. data/benchmark/client.rb +0 -117
  59. data/benchmark/server.rb +0 -120
  60. data/benchmark/thin_server.rb +0 -45
  61. data/lib/thrift/server/mongrel_http_server.rb +0 -60
  62. data/spec/BaseService.thrift +0 -27
  63. data/spec/ExtendedService.thrift +0 -25
  64. data/spec/Referenced.thrift +0 -44
  65. data/spec/ThriftNamespacedSpec.thrift +0 -53
  66. data/spec/ThriftSpec.thrift +0 -187
  67. data/spec/base_protocol_spec.rb +0 -224
  68. data/spec/base_transport_spec.rb +0 -387
  69. data/spec/binary_protocol_accelerated_spec.rb +0 -46
  70. data/spec/binary_protocol_spec.rb +0 -72
  71. data/spec/binary_protocol_spec_shared.rb +0 -445
  72. data/spec/bytes_spec.rb +0 -99
  73. data/spec/client_spec.rb +0 -166
  74. data/spec/compact_protocol_spec.rb +0 -196
  75. data/spec/constants_demo_spec.rb +0 -101
  76. data/spec/exception_spec.rb +0 -140
  77. data/spec/flat_spec.rb +0 -62
  78. data/spec/header_protocol_spec.rb +0 -475
  79. data/spec/header_transport_spec.rb +0 -386
  80. data/spec/http_client_spec.rb +0 -159
  81. data/spec/json_protocol_spec.rb +0 -552
  82. data/spec/namespaced_spec.rb +0 -66
  83. data/spec/nonblocking_server_spec.rb +0 -361
  84. data/spec/processor_spec.rb +0 -79
  85. data/spec/serializer_spec.rb +0 -66
  86. data/spec/server_socket_spec.rb +0 -84
  87. data/spec/server_spec.rb +0 -186
  88. data/spec/socket_spec.rb +0 -67
  89. data/spec/socket_spec_shared.rb +0 -167
  90. data/spec/spec_helper.rb +0 -69
  91. data/spec/ssl_server_socket_spec.rb +0 -45
  92. data/spec/ssl_socket_spec.rb +0 -87
  93. data/spec/struct_nested_containers_spec.rb +0 -190
  94. data/spec/struct_spec.rb +0 -397
  95. data/spec/support/header_protocol_helper.rb +0 -54
  96. data/spec/thin_http_server_spec.rb +0 -126
  97. data/spec/types_spec.rb +0 -117
  98. data/spec/union_spec.rb +0 -272
  99. data/spec/unix_socket_spec.rb +0 -115
  100. data/spec/uuid_validation_spec.rb +0 -238
  101. data/test/fuzz/Makefile.am +0 -173
  102. data/test/fuzz/README.md +0 -149
  103. data/test/fuzz/fuzz_common.rb +0 -95
  104. data/test/fuzz/fuzz_parse_binary_protocol.rb +0 -22
  105. data/test/fuzz/fuzz_parse_binary_protocol_accelerated.rb +0 -22
  106. data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +0 -22
  107. data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +0 -22
  108. data/test/fuzz/fuzz_parse_compact_protocol.rb +0 -22
  109. data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +0 -22
  110. data/test/fuzz/fuzz_parse_json_protocol.rb +0 -22
  111. data/test/fuzz/fuzz_parse_json_protocol_harness.rb +0 -22
  112. data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +0 -22
  113. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +0 -22
  114. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +0 -22
  115. data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +0 -22
  116. data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +0 -22
  117. data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +0 -22
  118. data/test/fuzz/fuzz_roundtrip_json_protocol.rb +0 -22
  119. data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +0 -22
  120. data/test/fuzz/fuzz_tracer.rb +0 -28
@@ -1,238 +0,0 @@
1
- #
2
- # Licensed to the Apache Software Foundation (ASF) under one
3
- # or more contributor license agreements. See the NOTICE file
4
- # distributed with this work for additional information
5
- # regarding copyright ownership. The ASF licenses this file
6
- # to you under the Apache License, Version 2.0 (the
7
- # "License"); you may not use this file except in compliance
8
- # with the License. You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing,
13
- # software distributed under the License is distributed on an
14
- # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
- # KIND, either express or implied. See the License for the
16
- # specific language governing permissions and limitations
17
- # under the License.
18
- #
19
-
20
- require 'spec_helper'
21
-
22
- describe 'UUID Validation' do
23
- protocols = [
24
- ['BinaryProtocol', Thrift::BinaryProtocol],
25
- ]
26
-
27
- if defined?(Thrift::BinaryProtocolAccelerated)
28
- protocols << ['BinaryProtocolAccelerated', Thrift::BinaryProtocolAccelerated]
29
- end
30
-
31
- protocols << ['CompactProtocol', Thrift::CompactProtocol]
32
- protocols << ['JsonProtocol', Thrift::JsonProtocol]
33
-
34
- protocols.each do |protocol_name, protocol_class|
35
- describe protocol_name do
36
- before(:each) do
37
- @trans = Thrift::MemoryBufferTransport.new
38
- @prot = protocol_class.new(@trans)
39
- end
40
-
41
- context 'valid UUIDs' do
42
- it 'should accept lowercase UUIDs' do
43
- uuid = '550e8400-e29b-41d4-a716-446655440000'
44
- expect { @prot.write_uuid(uuid) }.not_to raise_error
45
- result = @prot.read_uuid
46
- expect(result).to eq(uuid)
47
- end
48
-
49
- it 'should accept uppercase UUIDs' do
50
- uuid = '550E8400-E29B-41D4-A716-446655440000'
51
- expect { @prot.write_uuid(uuid) }.not_to raise_error
52
- result = @prot.read_uuid
53
- # Result should be lowercase
54
- expect(result).to eq('550e8400-e29b-41d4-a716-446655440000')
55
- end
56
-
57
- it 'should accept mixed case UUIDs' do
58
- uuid = '550e8400-E29B-41d4-A716-446655440000'
59
- expect { @prot.write_uuid(uuid) }.not_to raise_error
60
- result = @prot.read_uuid
61
- expect(result).to eq('550e8400-e29b-41d4-a716-446655440000')
62
- end
63
-
64
- it 'should accept all zeros' do
65
- uuid = '00000000-0000-0000-0000-000000000000'
66
- expect { @prot.write_uuid(uuid) }.not_to raise_error
67
- result = @prot.read_uuid
68
- expect(result).to eq(uuid)
69
- end
70
-
71
- it 'should accept all fs' do
72
- uuid = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
73
- expect { @prot.write_uuid(uuid) }.not_to raise_error
74
- result = @prot.read_uuid
75
- expect(result).to eq(uuid)
76
- end
77
- end
78
-
79
- context 'invalid UUIDs' do
80
- def expect_invalid_uuid(value, message)
81
- expect { @prot.write_uuid(value) }.to raise_error(Thrift::ProtocolException) do |error|
82
- expect(error.type).to eq(Thrift::ProtocolException::INVALID_DATA)
83
- expect(error.message).to eq(message)
84
- end
85
- end
86
-
87
- it 'should reject nil' do
88
- expect_invalid_uuid(nil, 'UUID must be a string')
89
- end
90
-
91
- it 'should reject non-string' do
92
- expect_invalid_uuid(12345, 'UUID must be a string')
93
- end
94
-
95
- it 'should reject wrong length' do
96
- expect_invalid_uuid('550e8400-e29b-41d4-a716', 'Invalid UUID format')
97
- end
98
-
99
- it 'should reject missing hyphens' do
100
- expect_invalid_uuid('550e8400e29b41d4a716446655440000', 'Invalid UUID format')
101
- end
102
-
103
- it 'should reject hyphens in wrong positions' do
104
- expect_invalid_uuid('550e840-0e29b-41d4-a716-446655440000', 'Invalid UUID format')
105
- end
106
-
107
- it 'should reject invalid hex characters (g)' do
108
- expect_invalid_uuid('550e8400-e29b-41d4-a716-44665544000g', 'Invalid UUID format')
109
- end
110
-
111
- it 'should reject invalid hex characters (z)' do
112
- expect_invalid_uuid('z50e8400-e29b-41d4-a716-446655440000', 'Invalid UUID format')
113
- end
114
-
115
- it 'should reject invalid hex characters (space)' do
116
- expect_invalid_uuid('550e8400-e29b-41d4-a716-44665544000 ', 'Invalid UUID format')
117
- end
118
-
119
- it 'should reject empty string' do
120
- expect_invalid_uuid('', 'Invalid UUID format')
121
- end
122
-
123
- it 'should reject UUID with extra characters' do
124
- expect_invalid_uuid('550e8400-e29b-41d4-a716-446655440000x', 'Invalid UUID format')
125
- end
126
-
127
- it 'should reject trailing hyphen' do
128
- expect_invalid_uuid('550e8400-e29b-41d4-a716-44665544000-', 'Invalid UUID format')
129
- end
130
-
131
- it 'should reject hyphen inside hex pair' do
132
- expect_invalid_uuid('550e8400-e29b-41d4-a716-4466-5544000', 'Invalid UUID format')
133
- end
134
- end
135
-
136
- context 'malformed binary data on read' do
137
- it 'should raise error on truncated data' do
138
- @trans = Thrift::MemoryBufferTransport.new
139
- @prot = protocol_class.new(@trans)
140
-
141
- # Write only 10 bytes instead of 16
142
- if protocol_class == Thrift::JsonProtocol
143
- @trans.write('"00000000-0000-0000-0000"')
144
- else
145
- @trans.write("\x00" * 10)
146
- end
147
-
148
- expect { @prot.read_uuid }.to raise_error(EOFError)
149
- end
150
-
151
- it 'should raise error on 15 bytes (one byte short)' do
152
- @trans = Thrift::MemoryBufferTransport.new
153
- @prot = protocol_class.new(@trans)
154
-
155
- if protocol_class == Thrift::JsonProtocol
156
- @trans.write('"00000000-0000-0000-0000-000000000"')
157
- else
158
- @trans.write("\x00" * 15)
159
- end
160
-
161
- expect { @prot.read_uuid }.to raise_error(EOFError)
162
- end
163
-
164
- it 'should raise error on empty buffer' do
165
- @trans = Thrift::MemoryBufferTransport.new
166
- @prot = protocol_class.new(@trans)
167
-
168
- expect { @prot.read_uuid }.to raise_error(EOFError)
169
- end
170
- end
171
-
172
- context 'multiple UUIDs in sequence' do
173
- it 'should handle 10 UUIDs in sequence' do
174
- uuids = 10.times.map { |i| sprintf('%08x-0000-0000-0000-000000000000', i) }
175
-
176
- @trans = Thrift::MemoryBufferTransport.new
177
- @prot = protocol_class.new(@trans)
178
-
179
- uuids.each { |uuid| @prot.write_uuid(uuid) }
180
-
181
- results = 10.times.map { @prot.read_uuid }
182
- expect(results).to eq(uuids)
183
- end
184
-
185
- it 'should handle UUIDs interleaved with other types' do
186
- @trans = Thrift::MemoryBufferTransport.new
187
- @prot = protocol_class.new(@trans)
188
-
189
- @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 0)
190
- @prot.write_i32(42)
191
- @prot.write_uuid('550e8400-e29b-41d4-a716-446655440000')
192
- @prot.write_string('test')
193
- @prot.write_uuid('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
194
- @prot.write_i64(123456789)
195
- @prot.write_message_end
196
-
197
- @prot.read_message_begin
198
- expect(@prot.read_i32).to eq(42)
199
- expect(@prot.read_uuid).to eq('550e8400-e29b-41d4-a716-446655440000')
200
- expect(@prot.read_string).to eq('test')
201
- expect(@prot.read_uuid).to eq('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
202
- expect(@prot.read_i64).to eq(123456789)
203
- @prot.read_message_end
204
- end
205
-
206
- it 'should handle UUIDs in struct fields context' do
207
- @trans = Thrift::MemoryBufferTransport.new
208
- @prot = protocol_class.new(@trans)
209
-
210
- # Simulate struct field headers
211
- @prot.write_struct_begin('test')
212
- @prot.write_field_begin('uuid1', Thrift::Types::UUID, 1)
213
- @prot.write_uuid('550e8400-e29b-41d4-a716-446655440000')
214
- @prot.write_field_end
215
- @prot.write_field_begin('uuid2', Thrift::Types::UUID, 2)
216
- @prot.write_uuid('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
217
- @prot.write_field_end
218
- @prot.write_field_stop
219
- @prot.write_struct_end
220
-
221
- @prot.read_struct_begin
222
- name, type, id = @prot.read_field_begin
223
- expect(type).to eq(Thrift::Types::UUID)
224
- expect(@prot.read_uuid).to eq('550e8400-e29b-41d4-a716-446655440000')
225
- @prot.read_field_end
226
-
227
- name, type, id = @prot.read_field_begin
228
- expect(type).to eq(Thrift::Types::UUID)
229
- expect(@prot.read_uuid).to eq('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
230
- @prot.read_field_end
231
-
232
- name, type, id = @prot.read_field_begin
233
- expect(type).to eq(Thrift::Types::STOP)
234
- end
235
- end
236
- end
237
- end
238
- end
@@ -1,173 +0,0 @@
1
- #
2
- # Licensed to the Apache Software Foundation (ASF) under one
3
- # or more contributor license agreements. See the NOTICE file
4
- # distributed with this work for additional information
5
- # regarding copyright ownership. The ASF licenses this file
6
- # to you under the Apache License, Version 2.0 (the
7
- # "License"); you may not use this file except in compliance
8
- # with the License. You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing,
13
- # software distributed under the License is distributed on an
14
- # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
- # KIND, either express or implied. See the License for the
16
- # specific language governing permissions and limitations
17
- # under the License.
18
- #
19
-
20
- THRIFT = $(top_builddir)/compiler/cpp/thrift
21
- FUZZ_RB_ROOT = $(top_srcdir)/lib/rb
22
- FUZZ_GEN_DIR = $(FUZZ_RB_ROOT)/test/fuzz
23
- FUZZ_STUBS = \
24
- $(FUZZ_GEN_DIR)/gen-rb/fuzz_test_constants.rb \
25
- $(FUZZ_GEN_DIR)/gen-rb/fuzz_test_types.rb
26
-
27
- FUZZ_RUBY_FILES = \
28
- $(srcdir)/fuzz_tracer.rb \
29
- $(srcdir)/fuzz_common.rb \
30
- $(srcdir)/fuzz_parse_binary_protocol.rb \
31
- $(srcdir)/fuzz_parse_binary_protocol_harness.rb \
32
- $(srcdir)/fuzz_parse_binary_protocol_accelerated.rb \
33
- $(srcdir)/fuzz_parse_binary_protocol_accelerated_harness.rb \
34
- $(srcdir)/fuzz_parse_compact_protocol.rb \
35
- $(srcdir)/fuzz_parse_compact_protocol_harness.rb \
36
- $(srcdir)/fuzz_parse_json_protocol.rb \
37
- $(srcdir)/fuzz_parse_json_protocol_harness.rb \
38
- $(srcdir)/fuzz_roundtrip_binary_protocol.rb \
39
- $(srcdir)/fuzz_roundtrip_binary_protocol_harness.rb \
40
- $(srcdir)/fuzz_roundtrip_binary_protocol_accelerated.rb \
41
- $(srcdir)/fuzz_roundtrip_binary_protocol_accelerated_harness.rb \
42
- $(srcdir)/fuzz_roundtrip_compact_protocol.rb \
43
- $(srcdir)/fuzz_roundtrip_compact_protocol_harness.rb \
44
- $(srcdir)/fuzz_roundtrip_json_protocol.rb \
45
- $(srcdir)/fuzz_roundtrip_json_protocol_harness.rb
46
-
47
- FUZZ_ASAN_OPTIONS ?= allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0
48
- FUZZ_CC ?= clang
49
- FUZZ_CXX ?= clang++
50
- FUZZ_LDSHARED ?= $(FUZZ_CC) -shared
51
- FUZZ_LDSHAREDXX ?= $(FUZZ_CXX) -shared
52
- FUZZ_CFLAGS ?= -fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g
53
- FUZZ_CXXFLAGS ?= -fsanitize=address,fuzzer-no-link -fno-omit-frame-pointer -fno-common -fPIC -g
54
- FUZZ_MAKE ?= make
55
- FUZZ_MAKEFLAGS ?= --environment-overrides V=1
56
-
57
- check: fuzz-prepare
58
-
59
- fuzz-prepare: $(FUZZ_STUBS)
60
- @for script in $(FUZZ_RUBY_FILES); do \
61
- $(RUBY) -c $$script; \
62
- done
63
- cd $(FUZZ_RB_ROOT) && \
64
- RUBYLIB="lib:test/fuzz/gen-rb" $(RUBY) -e 'require "thrift"; require "fuzz_test_types"; abort("Fuzz::FuzzTest is missing") unless defined?(Fuzz::FuzzTest)'
65
-
66
- $(THRIFT):
67
- $(MAKE) -C $(top_builddir)/compiler/cpp all
68
-
69
- $(FUZZ_STUBS): $(top_srcdir)/test/FuzzTest.thrift $(THRIFT)
70
- $(MKDIR_P) $(FUZZ_GEN_DIR)
71
- $(THRIFT) --gen rb -o $(FUZZ_GEN_DIR) $(top_srcdir)/test/FuzzTest.thrift
72
-
73
- fuzz-build-ext:
74
- cd $(FUZZ_RB_ROOT)/ext && \
75
- env MAKE="$(FUZZ_MAKE) $(FUZZ_MAKEFLAGS)" \
76
- CC="$(FUZZ_CC)" \
77
- CXX="$(FUZZ_CXX)" \
78
- LDSHARED="$(FUZZ_LDSHARED)" \
79
- LDSHAREDXX="$(FUZZ_LDSHAREDXX)" \
80
- CFLAGS="$(FUZZ_CFLAGS)" \
81
- CXXFLAGS="$(FUZZ_CXXFLAGS)" \
82
- $(RUBY) extconf.rb && \
83
- env MAKE="$(FUZZ_MAKE) $(FUZZ_MAKEFLAGS)" \
84
- CC="$(FUZZ_CC)" \
85
- CXX="$(FUZZ_CXX)" \
86
- LDSHARED="$(FUZZ_LDSHARED)" \
87
- LDSHAREDXX="$(FUZZ_LDSHAREDXX)" \
88
- CFLAGS="$(FUZZ_CFLAGS)" \
89
- CXXFLAGS="$(FUZZ_CXXFLAGS)" \
90
- $(FUZZ_MAKE) $(FUZZ_MAKEFLAGS) clean all
91
-
92
- fuzz-run: fuzz-prepare
93
- @test -n "$(TARGET)" || { echo 'Set TARGET=<fuzz script name>'; exit 1; }
94
- cd $(FUZZ_RB_ROOT) && \
95
- ASAN_OPTIONS="$(FUZZ_ASAN_OPTIONS)" \
96
- LD_PRELOAD=$$($(RUBY) -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
97
- $(RUBY) test/fuzz/$(TARGET) $(CORPUS) $(FUZZ_ARGS)
98
-
99
- fuzz-parse-binary:
100
- $(MAKE) $(AM_MAKEFLAGS) fuzz-run TARGET=fuzz_parse_binary_protocol.rb CORPUS="$(CORPUS)" FUZZ_ARGS="$(FUZZ_ARGS)"
101
-
102
- fuzz-parse-binary-accelerated: fuzz-build-ext
103
- $(MAKE) $(AM_MAKEFLAGS) fuzz-run TARGET=fuzz_parse_binary_protocol_accelerated.rb CORPUS="$(CORPUS)" FUZZ_ARGS="$(FUZZ_ARGS)"
104
-
105
- fuzz-parse-compact:
106
- $(MAKE) $(AM_MAKEFLAGS) fuzz-run TARGET=fuzz_parse_compact_protocol.rb CORPUS="$(CORPUS)" FUZZ_ARGS="$(FUZZ_ARGS)"
107
-
108
- fuzz-parse-json:
109
- $(MAKE) $(AM_MAKEFLAGS) fuzz-run TARGET=fuzz_parse_json_protocol.rb CORPUS="$(CORPUS)" FUZZ_ARGS="$(FUZZ_ARGS)"
110
-
111
- fuzz-roundtrip-binary:
112
- $(MAKE) $(AM_MAKEFLAGS) fuzz-run TARGET=fuzz_roundtrip_binary_protocol.rb CORPUS="$(CORPUS)" FUZZ_ARGS="$(FUZZ_ARGS)"
113
-
114
- fuzz-roundtrip-binary-accelerated: fuzz-build-ext
115
- $(MAKE) $(AM_MAKEFLAGS) fuzz-run TARGET=fuzz_roundtrip_binary_protocol_accelerated.rb CORPUS="$(CORPUS)" FUZZ_ARGS="$(FUZZ_ARGS)"
116
-
117
- fuzz-roundtrip-compact:
118
- $(MAKE) $(AM_MAKEFLAGS) fuzz-run TARGET=fuzz_roundtrip_compact_protocol.rb CORPUS="$(CORPUS)" FUZZ_ARGS="$(FUZZ_ARGS)"
119
-
120
- fuzz-roundtrip-json:
121
- $(MAKE) $(AM_MAKEFLAGS) fuzz-run TARGET=fuzz_roundtrip_json_protocol.rb CORPUS="$(CORPUS)" FUZZ_ARGS="$(FUZZ_ARGS)"
122
-
123
- fuzz-smoke-parse-binary:
124
- $(MAKE) $(AM_MAKEFLAGS) fuzz-parse-binary CORPUS="$(CORPUS)" FUZZ_ARGS="-runs=100 $(FUZZ_ARGS)"
125
-
126
- fuzz-smoke-parse-binary-accelerated:
127
- $(MAKE) $(AM_MAKEFLAGS) fuzz-parse-binary-accelerated CORPUS="$(CORPUS)" FUZZ_ARGS="-runs=100 $(FUZZ_ARGS)"
128
-
129
- fuzz-smoke-parse-compact:
130
- $(MAKE) $(AM_MAKEFLAGS) fuzz-parse-compact CORPUS="$(CORPUS)" FUZZ_ARGS="-runs=100 $(FUZZ_ARGS)"
131
-
132
- fuzz-smoke-parse-json:
133
- $(MAKE) $(AM_MAKEFLAGS) fuzz-parse-json CORPUS="$(CORPUS)" FUZZ_ARGS="-runs=100 $(FUZZ_ARGS)"
134
-
135
- fuzz-smoke-roundtrip-binary:
136
- $(MAKE) $(AM_MAKEFLAGS) fuzz-roundtrip-binary CORPUS="$(CORPUS)" FUZZ_ARGS="-runs=100 $(FUZZ_ARGS)"
137
-
138
- fuzz-smoke-roundtrip-binary-accelerated:
139
- $(MAKE) $(AM_MAKEFLAGS) fuzz-roundtrip-binary-accelerated CORPUS="$(CORPUS)" FUZZ_ARGS="-runs=100 $(FUZZ_ARGS)"
140
-
141
- fuzz-smoke-roundtrip-compact:
142
- $(MAKE) $(AM_MAKEFLAGS) fuzz-roundtrip-compact CORPUS="$(CORPUS)" FUZZ_ARGS="-runs=100 $(FUZZ_ARGS)"
143
-
144
- fuzz-smoke-roundtrip-json:
145
- $(MAKE) $(AM_MAKEFLAGS) fuzz-roundtrip-json CORPUS="$(CORPUS)" FUZZ_ARGS="-runs=100 $(FUZZ_ARGS)"
146
-
147
- clean-local:
148
- -$(RM) -r $(FUZZ_GEN_DIR)/gen-rb
149
-
150
- distdir:
151
- $(MAKE) $(AM_MAKEFLAGS) distdir-am
152
-
153
- EXTRA_DIST = \
154
- .gitignore \
155
- README.md \
156
- fuzz_common.rb \
157
- fuzz_tracer.rb \
158
- fuzz_parse_binary_protocol.rb \
159
- fuzz_parse_binary_protocol_harness.rb \
160
- fuzz_parse_binary_protocol_accelerated.rb \
161
- fuzz_parse_binary_protocol_accelerated_harness.rb \
162
- fuzz_parse_compact_protocol.rb \
163
- fuzz_parse_compact_protocol_harness.rb \
164
- fuzz_parse_json_protocol.rb \
165
- fuzz_parse_json_protocol_harness.rb \
166
- fuzz_roundtrip_binary_protocol.rb \
167
- fuzz_roundtrip_binary_protocol_harness.rb \
168
- fuzz_roundtrip_binary_protocol_accelerated.rb \
169
- fuzz_roundtrip_binary_protocol_accelerated_harness.rb \
170
- fuzz_roundtrip_compact_protocol.rb \
171
- fuzz_roundtrip_compact_protocol_harness.rb \
172
- fuzz_roundtrip_json_protocol.rb \
173
- fuzz_roundtrip_json_protocol_harness.rb
data/test/fuzz/README.md DELETED
@@ -1,149 +0,0 @@
1
- # Ruby Fuzzing README
2
-
3
- The Ruby Thrift implementation uses [Ruzzy](https://github.com/trailofbits/ruzzy) for fuzzing. Ruzzy is a coverage-guided fuzzer for pure Ruby code and Ruby C extensions.
4
-
5
- We currently have several fuzz targets that test different aspects of the Thrift implementation:
6
-
7
- - `fuzz_parse_binary_protocol.rb` -- fuzzes deserialization of the Binary protocol
8
- - `fuzz_parse_binary_protocol_accelerated.rb` -- fuzzes deserialization of the accelerated Binary protocol
9
- - `fuzz_parse_compact_protocol.rb` -- fuzzes deserialization of the Compact protocol
10
- - `fuzz_parse_json_protocol.rb` -- fuzzes JSON protocol messages
11
- - `fuzz_roundtrip_binary_protocol.rb` -- fuzzes Binary roundtrips (deserialize, serialize, deserialize, compare)
12
- - `fuzz_roundtrip_binary_protocol_accelerated.rb` -- fuzzes accelerated Binary roundtrips
13
- - `fuzz_roundtrip_compact_protocol.rb` -- fuzzes Compact roundtrips
14
- - `fuzz_roundtrip_json_protocol.rb` -- fuzzes JSON message roundtrips
15
-
16
- The runnable files in this directory are tracer entrypoints. Ruzzy requires that pure Ruby fuzzing starts from a tracer script which then loads a separate harness, so do not invoke the matching `_harness.rb` files directly.
17
-
18
- The fuzzers use Ruzzy's mutation engine to generate test cases. Each target uses common testing code from `fuzz_common.rb`.
19
-
20
- For more information about Ruzzy and its options, see the [Ruzzy documentation](https://github.com/trailofbits/ruzzy).
21
-
22
- You can also use the corpus generator from the Rust implementation to generate initial Binary and Compact corpora that can be reused by the Ruby fuzzers, since those wire formats are identical between implementations.
23
-
24
- ## Setup
25
-
26
- Run these commands from the repository root:
27
-
28
- ```bash
29
- apt install -y clang-19
30
-
31
- # from https://github.com/trailofbits/ruzzy?tab=readme-ov-file#installing
32
- MAKE="make --environment-overrides V=1" \
33
- CC="/usr/bin/clang-19" \
34
- CXX="/usr/bin/clang++-19" \
35
- LDSHARED="/usr/bin/clang-19 -shared" \
36
- LDSHAREDXX="/usr/bin/clang++-19 -shared" \
37
- gem install ruzzy
38
-
39
- # Validate the fuzz directory.
40
- # This generates test/fuzz/gen-rb, syntax-checks the fuzz scripts,
41
- # and verifies that Fuzz::FuzzTest loads correctly.
42
- make -C lib/rb/test/fuzz check
43
- ```
44
-
45
- `make -C lib/rb check` now recurses into `lib/rb/test/fuzz`, so the same validation also runs as part of the normal Ruby `make check` flow.
46
-
47
- ## Running Fuzzers
48
-
49
- The Makefile in this directory hides the `LD_PRELOAD` and `ASAN_OPTIONS` setup needed by Ruzzy.
50
-
51
- Pure Ruby targets only need `fuzz-prepare`, which is the same work as `check`:
52
-
53
- ```bash
54
- make -C lib/rb/test/fuzz fuzz-parse-binary
55
- make -C lib/rb/test/fuzz fuzz-roundtrip-compact
56
- make -C lib/rb/test/fuzz fuzz-parse-json
57
- ```
58
-
59
- Accelerated targets rebuild `thrift_native` with sanitizer flags first:
60
-
61
- ```bash
62
- make -C lib/rb/test/fuzz fuzz-parse-binary-accelerated
63
- make -C lib/rb/test/fuzz fuzz-roundtrip-binary-accelerated
64
- ```
65
-
66
- Use `CORPUS=...` to point at an input corpus. The path is resolved from `lib/rb`, which matches the old manual commands:
67
-
68
- ```bash
69
- make -C lib/rb/test/fuzz fuzz-parse-binary \
70
- CORPUS=../rs/test/fuzz/corpus/binary
71
-
72
- make -C lib/rb/test/fuzz fuzz-parse-compact \
73
- CORPUS=../rs/test/fuzz/corpus/compact
74
- ```
75
-
76
- Use `FUZZ_ARGS=...` for extra libFuzzer-style arguments. For a short local run, the Makefile also provides bounded smoke targets:
77
-
78
- ```bash
79
- make -C lib/rb/test/fuzz fuzz-smoke-parse-binary
80
- make -C lib/rb/test/fuzz fuzz-smoke-parse-binary-accelerated \
81
- FUZZ_CC=/usr/bin/clang-19 \
82
- FUZZ_CXX=/usr/bin/clang++-19
83
- ```
84
-
85
- If the default `clang` and `clang++` names are not correct for your system, override these variables for accelerated targets:
86
-
87
- ```bash
88
- make -C lib/rb/test/fuzz fuzz-build-ext \
89
- FUZZ_CC=/usr/bin/clang-19 \
90
- FUZZ_CXX=/usr/bin/clang++-19
91
- ```
92
-
93
- The underlying manual command from `lib/rb` is still:
94
-
95
- ```bash
96
- # Memory allocation failures are common and low impact (DoS), so skip them for now.
97
- # Like Python, the Ruby interpreter leaks data, so ignore these for now.
98
- # Ruby recommends disabling sigaltstack.
99
- export ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0"
100
-
101
- LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \
102
- ruby test/fuzz/fuzz_parse_binary_protocol.rb
103
- ```
104
-
105
- ## Rust Corpus Generator
106
-
107
- We can use the Rust corpus generator to prepare corpora for the Binary and Compact protocol targets. Run it from the repository root:
108
-
109
- ```bash
110
- cargo run --manifest-path lib/rs/test/fuzz/Cargo.toml --bin corpus_generator -- \
111
- --output-dir <output_dir> \
112
- --protocol <binary|compact> \
113
- --generate <num_files> \
114
- --buffer-size <buffer_size> \
115
- --random-size <random_size>
116
- ```
117
-
118
- Reasonable values (determined empirically):
119
-
120
- ```bash
121
- cargo run --manifest-path lib/rs/test/fuzz/Cargo.toml --bin corpus_generator -- \
122
- --output-dir ./lib/rs/test/fuzz/corpus/binary \
123
- --protocol binary \
124
- --generate 1000 \
125
- --buffer-size 65536 \
126
- --random-size 16384
127
-
128
- cargo run --manifest-path lib/rs/test/fuzz/Cargo.toml --bin corpus_generator -- \
129
- --output-dir ./lib/rs/test/fuzz/corpus/compact \
130
- --protocol compact \
131
- --generate 1000 \
132
- --buffer-size 16384 \
133
- --random-size 16384
134
- ```
135
-
136
- Then run a matching Ruby target:
137
-
138
- ```bash
139
- make -C lib/rb/test/fuzz fuzz-parse-binary \
140
- CORPUS=../rs/test/fuzz/corpus/binary
141
- ```
142
-
143
- The Rust corpus generator does not emit JSON protocol inputs, so use it only with the Binary and Compact Ruby targets.
144
-
145
- ## Troubleshooting
146
-
147
- If libFuzzer prints `WARNING: no interesting inputs were found so far. Is the code instrumented for coverage?` and quickly shrinks the seed corpus to `corp: 1/1b`, coverage tracing is not active. That usually means the tracer script was bypassed or `ruzzy` was not installed with the expected sanitizer-enabled toolchain. Run the `.rb` files in this directory, not the `_harness.rb` files.
148
-
149
- If an accelerated target starts using the pure Ruby implementation, rebuild the extension with `make -C lib/rb/test/fuzz fuzz-build-ext ...` and then rerun the accelerated target.
@@ -1,95 +0,0 @@
1
- #
2
- # Licensed to the Apache Software Foundation (ASF) under one
3
- # or more contributor license agreements. See the NOTICE file
4
- # distributed with this work for additional information
5
- # regarding copyright ownership. The ASF licenses this file
6
- # to you under the Apache License, Version 2.0 (the
7
- # "License"); you may not use this file except in compliance
8
- # with the License. You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing,
13
- # software distributed under the License is distributed on an
14
- # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
- # KIND, either express or implied. See the License for the
16
- # specific language governing permissions and limitations
17
- # under the License.
18
- #
19
-
20
- $:.unshift File.expand_path('../../lib', __dir__)
21
- $:.unshift File.expand_path('../../ext', __dir__)
22
- require 'thrift'
23
- $:.unshift File.dirname(__FILE__) + "/gen-rb"
24
- require 'fuzz_test_constants'
25
-
26
- require 'coverage'
27
- Coverage.start(branches: true) unless Coverage.respond_to?(:running?) && Coverage.running?
28
- require 'ruzzy'
29
- # Ruzzy.enable_branch_coverage_hooks
30
-
31
- def ignorable_fuzz_exception?(error)
32
- return true if error.is_a?(Thrift::ProtocolException) ||
33
- error.is_a?(EOFError) ||
34
- error.is_a?(Encoding::UndefinedConversionError)
35
-
36
- [
37
- /don't know what (?:c)?type/,
38
- /Too many fields for union/,
39
- /too big to convert to '(?:int|long)'/,
40
- /bignum too big to convert into 'long'/,
41
- /negative array size/,
42
- /Union fields are not set/
43
- ].any? { |pattern| error.message =~ pattern }
44
- end
45
-
46
- def read_fuzz_test(protocol, read_message_begin)
47
- protocol.read_message_begin if read_message_begin
48
- obj = Fuzz::FuzzTest.new
49
- obj.read(protocol)
50
- protocol.read_message_end if read_message_begin
51
- obj
52
- end
53
-
54
- def write_fuzz_test(protocol, obj, write_message_begin)
55
- if write_message_begin
56
- protocol.write_message_begin('fuzz', Thrift::MessageTypes::CALL, 0)
57
- end
58
- obj.write(protocol)
59
- protocol.write_message_end if write_message_begin
60
- end
61
-
62
- def create_parser_fuzzer(protocol_factory_class, read_message_begin: false)
63
- lambda do |data|
64
- transport = Thrift::MemoryBufferTransport.new(data)
65
- protocol = protocol_factory_class.new.get_protocol(transport)
66
- read_fuzz_test(protocol, read_message_begin)
67
- 0
68
- rescue StandardError => e
69
- # We're looking for memory corruption, not Ruby exceptions
70
- raise unless ignorable_fuzz_exception?(e)
71
- end
72
- end
73
-
74
- def create_roundtrip_fuzzer(protocol_factory_class, read_message_begin: false)
75
- lambda do |data|
76
- transport = Thrift::MemoryBufferTransport.new(data)
77
- protocol = protocol_factory_class.new.get_protocol(transport)
78
- obj = read_fuzz_test(protocol, read_message_begin)
79
-
80
- serialized_data = +""
81
- transport2 = Thrift::MemoryBufferTransport.new(serialized_data)
82
- protocol2 = protocol_factory_class.new.get_protocol(transport2)
83
- write_fuzz_test(protocol2, obj, read_message_begin)
84
-
85
- transport3 = Thrift::MemoryBufferTransport.new(serialized_data)
86
- protocol3 = protocol_factory_class.new.get_protocol(transport3)
87
- deserialized_obj = read_fuzz_test(protocol3, read_message_begin)
88
-
89
- raise "Roundtrip mismatch" unless obj == deserialized_obj
90
- 0
91
- rescue StandardError => e
92
- # We're looking for memory corruption, not Ruby exceptions
93
- raise unless ignorable_fuzz_exception?(e)
94
- end
95
- end
@@ -1,22 +0,0 @@
1
- #
2
- # Licensed to the Apache Software Foundation (ASF) under one
3
- # or more contributor license agreements. See the NOTICE file
4
- # distributed with this work for additional information
5
- # regarding copyright ownership. The ASF licenses this file
6
- # to you under the Apache License, Version 2.0 (the
7
- # "License"); you may not use this file except in compliance
8
- # with the License. You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing,
13
- # software distributed under the License is distributed on an
14
- # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
- # KIND, either express or implied. See the License for the
16
- # specific language governing permissions and limitations
17
- # under the License.
18
- #
19
-
20
- require_relative 'fuzz_tracer'
21
-
22
- trace_fuzz_target(__FILE__)