libddwaf 1.14.0.0.0 → 1.18.0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/actions/docker-build-ruby/Dockerfile +5 -0
- data/.github/actions/docker-build-ruby/Dockerfile.alpine +7 -0
- data/.github/actions/docker-build-ruby/Dockerfile.jruby +6 -0
- data/.github/actions/docker-build-ruby/action.yml +57 -0
- data/.github/workflows/lint.yml +13 -12
- data/.github/workflows/package.yml +93 -174
- data/.github/workflows/test.yml +86 -190
- data/.gitignore +4 -1
- data/.steepignore +4 -0
- data/CHANGELOG.md +5 -1
- data/lib/datadog/appsec/waf/context.rb +122 -0
- data/lib/datadog/appsec/waf/converter.rb +172 -0
- data/lib/datadog/appsec/waf/handle.rb +108 -0
- data/lib/datadog/appsec/waf/lib_ddwaf.rb +307 -0
- data/lib/datadog/appsec/waf/result.rb +33 -0
- data/lib/datadog/appsec/waf/version.rb +2 -2
- data/lib/datadog/appsec/waf.rb +17 -670
- data/sig/datadog/appsec/waf/context.rbs +39 -0
- data/sig/datadog/appsec/waf/converter.rbs +11 -0
- data/sig/datadog/appsec/waf/handle.rbs +42 -0
- data/sig/datadog/appsec/waf/lib_ddwaf.rbs +156 -0
- data/sig/datadog/appsec/waf/result.rbs +33 -0
- data/sig/datadog/appsec/waf.rbs +1 -201
- metadata +22 -8
- data/vendor/rbs/ffi/0/ffi.rbs +0 -62
data/.github/workflows/test.yml
CHANGED
@@ -3,220 +3,116 @@ on:
|
|
3
3
|
- push
|
4
4
|
|
5
5
|
jobs:
|
6
|
-
test-linux:
|
6
|
+
test-cruby-linux:
|
7
7
|
strategy:
|
8
8
|
fail-fast: false
|
9
9
|
matrix:
|
10
|
+
os: [ubuntu-24.04]
|
11
|
+
ruby: ["2.5", "2.6", "2.7", "3.0", "3.1", "3.2", "3.3"]
|
12
|
+
arch: [amd64, arm64]
|
13
|
+
libc: [gnu, musl]
|
10
14
|
include:
|
11
|
-
-
|
12
|
-
cpu: x86_64
|
15
|
+
- arch: amd64
|
13
16
|
platform: x86_64-linux
|
14
|
-
|
15
|
-
qemu: amd64
|
16
|
-
libc: gnu
|
17
|
-
- os: ubuntu-20.04
|
18
|
-
cpu: aarch64
|
17
|
+
- arch: arm64
|
19
18
|
platform: aarch64-linux
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
qemu: arm64
|
58
|
-
libc: gnu
|
59
|
-
- os: ubuntu-20.04
|
60
|
-
cpu: x86_64
|
61
|
-
platform: x86_64-linux
|
62
|
-
image: ruby:2.5
|
63
|
-
qemu: amd64
|
64
|
-
libc: gnu
|
65
|
-
- os: ubuntu-20.04
|
66
|
-
cpu: x86_64
|
67
|
-
platform: x86_64-linux
|
68
|
-
image: ruby:2.4
|
69
|
-
qemu: amd64
|
70
|
-
libc: gnu
|
71
|
-
- os: ubuntu-20.04
|
72
|
-
cpu: x86_64
|
73
|
-
platform: x86_64-linux
|
74
|
-
image: ruby:2.3
|
75
|
-
qemu: amd64
|
76
|
-
libc: gnu
|
77
|
-
- os: ubuntu-20.04
|
78
|
-
cpu: x86_64
|
79
|
-
platform: x86_64-linux
|
80
|
-
image: ruby:2.2
|
81
|
-
qemu: amd64
|
82
|
-
libc: gnu
|
83
|
-
- os: ubuntu-20.04
|
84
|
-
cpu: x86_64
|
85
|
-
platform: x86_64-linux
|
86
|
-
image: ruby:2.1
|
87
|
-
qemu: amd64
|
88
|
-
libc: gnu
|
89
|
-
- os: ubuntu-20.04
|
90
|
-
cpu: x86_64
|
91
|
-
platform: x86_64-linux
|
92
|
-
image: ruby:3.1-alpine
|
93
|
-
qemu: amd64
|
94
|
-
libc: musl
|
95
|
-
- os: ubuntu-20.04
|
96
|
-
cpu: aarch64
|
97
|
-
platform: aarch64-linux
|
98
|
-
image: ruby:3.1-alpine
|
99
|
-
qemu: arm64
|
100
|
-
libc: musl
|
101
|
-
- os: ubuntu-20.04
|
102
|
-
cpu: x86_64
|
103
|
-
platform: x86_64-linux
|
104
|
-
image: ruby:3.0-alpine
|
105
|
-
qemu: amd64
|
106
|
-
libc: musl
|
107
|
-
- os: ubuntu-20.04
|
108
|
-
cpu: aarch64
|
109
|
-
platform: aarch64-linux
|
110
|
-
image: ruby:3.0-alpine
|
111
|
-
qemu: arm64
|
112
|
-
libc: musl
|
113
|
-
- os: ubuntu-20.04
|
114
|
-
cpu: x86_64
|
115
|
-
platform: x86_64-linux
|
116
|
-
image: ruby:2.7-alpine
|
117
|
-
qemu: amd64
|
118
|
-
libc: musl
|
119
|
-
- os: ubuntu-20.04
|
120
|
-
cpu: aarch64
|
121
|
-
platform: aarch64-linux
|
122
|
-
image: ruby:2.7-alpine
|
123
|
-
qemu: arm64
|
124
|
-
libc: musl
|
125
|
-
- os: ubuntu-20.04
|
126
|
-
cpu: x86_64
|
19
|
+
|
20
|
+
name: Test (Ruby ${{ matrix.ruby }}, ${{ matrix.arch }}, ${{ matrix.libc }})
|
21
|
+
runs-on: ${{ matrix.os }}
|
22
|
+
|
23
|
+
steps:
|
24
|
+
- name: Checkout
|
25
|
+
uses: actions/checkout@v4
|
26
|
+
|
27
|
+
- name: Build docker image
|
28
|
+
id: build-image
|
29
|
+
uses: ./.github/actions/docker-build-ruby
|
30
|
+
with:
|
31
|
+
ruby-version: ${{ matrix.ruby }}
|
32
|
+
arch: ${{ matrix.arch }}
|
33
|
+
libc: ${{ matrix.libc }}
|
34
|
+
|
35
|
+
- name: Bundle install
|
36
|
+
run: ${{ steps.build-image.outputs.run-cmd }} bundle install
|
37
|
+
|
38
|
+
- name: Fetch binary library
|
39
|
+
run: ${{ steps.build-image.outputs.run-cmd }} bundle exec rake fetch[${{ matrix.platform }}]
|
40
|
+
|
41
|
+
- name: Extract binary library
|
42
|
+
run: ${{ steps.build-image.outputs.run-cmd }} bundle exec rake extract[${{ matrix.platform }}]
|
43
|
+
|
44
|
+
- name: Run specs
|
45
|
+
run: ${{ steps.build-image.outputs.run-cmd }} bundle exec rake spec
|
46
|
+
|
47
|
+
test-jruby-linux:
|
48
|
+
strategy:
|
49
|
+
fail-fast: false
|
50
|
+
matrix:
|
51
|
+
os: [ubuntu-24.04]
|
52
|
+
jruby: ["9.3", "9.4"]
|
53
|
+
arch: [amd64, arm64]
|
54
|
+
include:
|
55
|
+
- arch: amd64
|
127
56
|
platform: x86_64-linux
|
128
|
-
|
129
|
-
qemu: amd64
|
130
|
-
libc: musl
|
131
|
-
- os: ubuntu-20.04
|
132
|
-
cpu: aarch64
|
57
|
+
- arch: arm64
|
133
58
|
platform: aarch64-linux
|
134
|
-
|
135
|
-
|
136
|
-
libc: musl
|
137
|
-
# TODO: jruby images have no sudo so apt-get can't get a lock
|
138
|
-
# - os: ubuntu-20.04
|
139
|
-
# cpu: x86_64
|
140
|
-
# platform: x86_64-linux-gnu
|
141
|
-
# image: jruby:9.3.0.0
|
142
|
-
# qemu: amd64
|
143
|
-
# libc: gnu
|
144
|
-
# - os: ubuntu-20.04
|
145
|
-
# cpu: x86_64
|
146
|
-
# platform: x86_64-linux-gnu
|
147
|
-
# image: jruby:9.2.8.0
|
148
|
-
# qemu: amd64
|
149
|
-
# libc: gnu
|
150
|
-
# - os: ubuntu-20.04
|
151
|
-
# cpu: x86_64
|
152
|
-
# platform: aarch64-linux-gnu
|
153
|
-
# image: jruby:9.3.4.0
|
154
|
-
# qemu: arm64
|
155
|
-
# libc: gnu
|
156
|
-
name: Test (${{ matrix.image }}, ${{ matrix.cpu }})
|
59
|
+
|
60
|
+
name: Test (Jruby ${{ matrix.jruby }}, ${{ matrix.arch }})
|
157
61
|
runs-on: ${{ matrix.os }}
|
62
|
+
|
158
63
|
steps:
|
159
|
-
- name: Enable ${{ matrix.qemu }} platform
|
160
|
-
id: qemu
|
161
|
-
if: ${{ matrix.cpu != 'amd64' }}
|
162
|
-
run: |
|
163
|
-
docker run --privileged --rm tonistiigi/binfmt:latest --install ${{ matrix.qemu }} | tee platforms.json
|
164
|
-
echo "::set-output name=platforms::$(cat platforms.json)"
|
165
|
-
- name: Start container
|
166
|
-
id: container
|
167
|
-
run: |
|
168
|
-
echo ${{ matrix.image }} > container_image
|
169
|
-
docker run --rm -d -v "${PWD}":"${PWD}" -w "${PWD}" --platform linux/${{ matrix.qemu }} ${{ matrix.image }} /bin/sleep 64d | tee container_id
|
170
|
-
docker exec -w "${PWD}" $(cat container_id) uname -a
|
171
|
-
echo "::set-output name=id::$(cat container_id)"
|
172
|
-
- name: Install Alpine system dependencies
|
173
|
-
if: ${{ matrix.libc == 'musl' }}
|
174
|
-
run: docker exec -w "${PWD}" ${{ steps.container.outputs.id }} apk add --no-cache build-base git
|
175
|
-
- name: Install JRuby system dependencies
|
176
|
-
if: ${{ startsWith(matrix.image, 'jruby') }}
|
177
|
-
run: |
|
178
|
-
docker exec -w "${PWD}" ${{ steps.container.outputs.id }} sudo apt-get update
|
179
|
-
docker exec -w "${PWD}" ${{ steps.container.outputs.id }} sudo apt-get install -y build-essential git
|
180
64
|
- name: Checkout
|
181
|
-
uses: actions/checkout@
|
182
|
-
|
183
|
-
|
184
|
-
|
65
|
+
uses: actions/checkout@v4
|
66
|
+
|
67
|
+
- name: Build docker image
|
68
|
+
id: build-image
|
69
|
+
uses: ./.github/actions/docker-build-ruby
|
70
|
+
with:
|
71
|
+
ruby-version: ${{ matrix.jruby }}
|
72
|
+
jruby: true
|
73
|
+
arch: ${{ matrix.arch }}
|
74
|
+
libc: gnu
|
75
|
+
|
76
|
+
- name: Bundle install
|
77
|
+
run: ${{ steps.build-image.outputs.run-cmd }} bundle install
|
78
|
+
|
185
79
|
- name: Fetch binary library
|
186
|
-
run:
|
187
|
-
|
80
|
+
run: ${{ steps.build-image.outputs.run-cmd }} bundle exec rake fetch[${{ matrix.platform }}]
|
81
|
+
|
188
82
|
- name: Extract binary library
|
189
|
-
run:
|
190
|
-
|
83
|
+
run: ${{ steps.build-image.outputs.run-cmd }} bundle exec rake extract[${{ matrix.platform }}]
|
84
|
+
|
191
85
|
- name: Run specs
|
192
|
-
run:
|
193
|
-
|
86
|
+
run: ${{ steps.build-image.outputs.run-cmd }} bundle exec rake spec
|
87
|
+
|
194
88
|
test-darwin:
|
195
89
|
strategy:
|
196
90
|
fail-fast: false
|
197
91
|
matrix:
|
92
|
+
os: [macos-15, macos-15-large]
|
198
93
|
include:
|
199
|
-
- os: macos-
|
200
|
-
|
94
|
+
- os: macos-15
|
95
|
+
platform: arm64-darwin
|
96
|
+
- os: macos-15-large
|
201
97
|
platform: x86_64-darwin
|
202
|
-
|
203
|
-
|
204
|
-
# platform: arm64-darwin
|
205
|
-
name: Test (${{ matrix.os }} ${{ matrix.cpu }})
|
98
|
+
|
99
|
+
name: Test (${{ matrix.os }})
|
206
100
|
runs-on: ${{ matrix.os }}
|
101
|
+
env:
|
102
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
103
|
+
|
207
104
|
steps:
|
208
105
|
- name: Checkout
|
209
|
-
uses: actions/checkout@
|
106
|
+
uses: actions/checkout@v4
|
107
|
+
|
210
108
|
- name: Bundle
|
211
|
-
run:
|
212
|
-
|
109
|
+
run: bundle install
|
110
|
+
|
213
111
|
- name: Fetch binary library
|
214
|
-
run:
|
215
|
-
|
112
|
+
run: bundle exec rake fetch[${{ matrix.platform }}]
|
113
|
+
|
216
114
|
- name: Extract binary library
|
217
|
-
run:
|
218
|
-
bundle exec rake extract[${{ matrix.platform }}]
|
219
|
-
- name: Run specs
|
220
|
-
run: |
|
221
|
-
bundle exec rake spec
|
115
|
+
run: bundle exec rake extract[${{ matrix.platform }}]
|
222
116
|
|
117
|
+
- name: Run specs
|
118
|
+
run: bundle exec rake spec
|
data/.gitignore
CHANGED
data/.steepignore
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
ffi/library.rbs:36:45 "Type `::FFI::DataConverter` is generic but used as a non generic type"
|
2
|
+
ffi/struct.rbs:5:15 "Type application of `::FFI::Type::Mapped` doesn't satisfy the constraints"
|
3
|
+
ffi/struct.rbs:23:29 "Type application of `::FFI::Type::Mapped` doesn't satisfy the constraints"
|
4
|
+
ffi/auto_pointer.rbs:15:65 "Type application of `::FFI::AutoPointer::Releaser::_Proc` doesn't satisfy the constraints"
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# 2024-10-29 v.1.15.0.0.0
|
2
|
+
- Update to libddwaf 1.15.0
|
3
|
+
- Changed `Datadog::AppSec::WAF::Context#run` interface to accommodate ephemeral data ([Breaking change](https://github.com/DataDog/libddwaf/blob/master/CHANGELOG.md#v1150-unstable))
|
4
|
+
|
1
5
|
# 2023-09-11 v.1.14.0.0.0
|
2
6
|
- Update to libddwaf 1.14.0
|
3
7
|
- Add support for `Float` and `Nil` scalar values when converting from ruby to WAF Object and vice versa.
|
@@ -6,7 +10,7 @@
|
|
6
10
|
# 2023-08-29 v.1.11.0.0.0
|
7
11
|
|
8
12
|
- Update to libddwaf 1.11.0
|
9
|
-
- Changed `Datadog::AppSec::WAF::Handle#ruleset_info` to `Datadog::AppSec::WAF::Handle#diagnostics
|
13
|
+
- Changed `Datadog::AppSec::WAF::Handle#ruleset_info` to `Datadog::AppSec::WAF::Handle#diagnostics`. (Breaking change)
|
10
14
|
The schema of the diagnostics variable can be found [here](https://github.com/DataDog/libddwaf/blob/master/schema/diagnostics.json)
|
11
15
|
- Changed `Datadog::AppSec::WAF::Result#data` to `Datadog::AppSec::WAF::Result#events`. (Breaking change)
|
12
16
|
The schema of the events variable can be found [here](https://github.com/DataDog/libddwaf/blob/master/schema/events.json)
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module WAF
|
6
|
+
# Ruby representation of the ddwaf_context in libddwaf
|
7
|
+
# See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/BINDING_IMPL_NOTES.md?plain=1#L125-L158
|
8
|
+
class Context
|
9
|
+
RESULT_CODE = {
|
10
|
+
ddwaf_ok: :ok,
|
11
|
+
ddwaf_match: :match,
|
12
|
+
ddwaf_err_internal: :err_internal,
|
13
|
+
ddwaf_err_invalid_object: :err_invalid_object,
|
14
|
+
ddwaf_err_invalid_argument: :err_invalid_argument
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
attr_reader :context_obj
|
18
|
+
|
19
|
+
def initialize(handle)
|
20
|
+
handle_obj = handle.handle_obj
|
21
|
+
retain(handle)
|
22
|
+
|
23
|
+
@context_obj = LibDDWAF.ddwaf_context_init(handle_obj)
|
24
|
+
raise LibDDWAF::Error, 'Could not create context' if @context_obj.null?
|
25
|
+
|
26
|
+
validate!
|
27
|
+
end
|
28
|
+
|
29
|
+
def finalize
|
30
|
+
invalidate!
|
31
|
+
|
32
|
+
retained.each do |retained_obj|
|
33
|
+
next unless retained_obj.is_a?(LibDDWAF::Object)
|
34
|
+
|
35
|
+
LibDDWAF.ddwaf_object_free(retained_obj)
|
36
|
+
end
|
37
|
+
|
38
|
+
LibDDWAF.ddwaf_context_destroy(context_obj)
|
39
|
+
end
|
40
|
+
|
41
|
+
def run(persistent_data, ephemeral_data, timeout = LibDDWAF::DDWAF_RUN_TIMEOUT)
|
42
|
+
valid!
|
43
|
+
|
44
|
+
persistent_data_obj = Converter.ruby_to_object(
|
45
|
+
persistent_data,
|
46
|
+
max_container_size: LibDDWAF::DDWAF_MAX_CONTAINER_SIZE,
|
47
|
+
max_container_depth: LibDDWAF::DDWAF_MAX_CONTAINER_DEPTH,
|
48
|
+
max_string_length: LibDDWAF::DDWAF_MAX_STRING_LENGTH,
|
49
|
+
coerce: false
|
50
|
+
)
|
51
|
+
if persistent_data_obj.null?
|
52
|
+
raise LibDDWAF::Error, "Could not convert persistent data: #{persistent_data.inspect}"
|
53
|
+
end
|
54
|
+
|
55
|
+
# retain C objects in memory for subsequent calls to run
|
56
|
+
retain(persistent_data_obj)
|
57
|
+
|
58
|
+
ephemeral_data_obj = Converter.ruby_to_object(
|
59
|
+
ephemeral_data,
|
60
|
+
max_container_size: LibDDWAF::DDWAF_MAX_CONTAINER_SIZE,
|
61
|
+
max_container_depth: LibDDWAF::DDWAF_MAX_CONTAINER_DEPTH,
|
62
|
+
max_string_length: LibDDWAF::DDWAF_MAX_STRING_LENGTH,
|
63
|
+
coerce: false
|
64
|
+
)
|
65
|
+
if ephemeral_data_obj.null?
|
66
|
+
raise LibDDWAF::Error, "Could not convert ephemeral data: #{ephemeral_data.inspect}"
|
67
|
+
end
|
68
|
+
|
69
|
+
result_obj = LibDDWAF::Result.new
|
70
|
+
raise LibDDWAF::Error, 'Could not create result object' if result_obj.null?
|
71
|
+
|
72
|
+
code = LibDDWAF.ddwaf_run(@context_obj, persistent_data_obj, ephemeral_data_obj, result_obj, timeout)
|
73
|
+
|
74
|
+
result = Result.new(
|
75
|
+
RESULT_CODE[code],
|
76
|
+
Converter.object_to_ruby(result_obj[:events]),
|
77
|
+
result_obj[:total_runtime],
|
78
|
+
result_obj[:timeout],
|
79
|
+
Converter.object_to_ruby(result_obj[:actions]),
|
80
|
+
Converter.object_to_ruby(result_obj[:derivatives])
|
81
|
+
)
|
82
|
+
|
83
|
+
[RESULT_CODE[code], result]
|
84
|
+
ensure
|
85
|
+
LibDDWAF.ddwaf_result_free(result_obj) if result_obj
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def validate!
|
91
|
+
@valid = true
|
92
|
+
end
|
93
|
+
|
94
|
+
def invalidate!
|
95
|
+
@valid = false
|
96
|
+
end
|
97
|
+
|
98
|
+
def valid?
|
99
|
+
@valid
|
100
|
+
end
|
101
|
+
|
102
|
+
def valid!
|
103
|
+
return if valid?
|
104
|
+
|
105
|
+
raise LibDDWAF::Error, "Attempt to use an invalid instance: #{inspect}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def retained
|
109
|
+
@retained ||= []
|
110
|
+
end
|
111
|
+
|
112
|
+
def retain(object)
|
113
|
+
retained << object
|
114
|
+
end
|
115
|
+
|
116
|
+
def release(object)
|
117
|
+
retained.delete(object)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module WAF
|
6
|
+
# Module responsible for Ruby-to-C and C-to-Ruby conversions
|
7
|
+
module Converter
|
8
|
+
module_function
|
9
|
+
|
10
|
+
# rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
11
|
+
def ruby_to_object(val, max_container_size: nil, max_container_depth: nil, max_string_length: nil, coerce: true)
|
12
|
+
case val
|
13
|
+
when Array
|
14
|
+
obj = LibDDWAF::Object.new
|
15
|
+
res = LibDDWAF.ddwaf_object_array(obj)
|
16
|
+
if res.null?
|
17
|
+
raise LibDDWAF::Error, "Could not convert into object: #{val}"
|
18
|
+
end
|
19
|
+
|
20
|
+
max_index = max_container_size - 1 if max_container_size
|
21
|
+
val.each.with_index do |e, i| # rubocop:disable Style/MultilineIfModifier
|
22
|
+
member = Converter.ruby_to_object(e,
|
23
|
+
max_container_size: max_container_size,
|
24
|
+
max_container_depth: (max_container_depth - 1 if max_container_depth),
|
25
|
+
max_string_length: max_string_length,
|
26
|
+
coerce: coerce)
|
27
|
+
e_res = LibDDWAF.ddwaf_object_array_add(obj, member)
|
28
|
+
raise LibDDWAF::Error, "Could not add to array object: #{e.inspect}" unless e_res
|
29
|
+
|
30
|
+
break val if max_index && i >= max_index
|
31
|
+
end unless max_container_depth == 0
|
32
|
+
|
33
|
+
obj
|
34
|
+
when Hash
|
35
|
+
obj = LibDDWAF::Object.new
|
36
|
+
res = LibDDWAF.ddwaf_object_map(obj)
|
37
|
+
if res.null?
|
38
|
+
raise LibDDWAF::Error, "Could not convert into object: #{val}"
|
39
|
+
end
|
40
|
+
|
41
|
+
max_index = max_container_size - 1 if max_container_size
|
42
|
+
val.each.with_index do |e, i| # rubocop:disable Style/MultilineIfModifier
|
43
|
+
# for Steep, which doesn't handle |(k, v), i|
|
44
|
+
k, v = e[0], e[1] # rubocop:disable Style/ParallelAssignment
|
45
|
+
|
46
|
+
k = k.to_s[0, max_string_length] if max_string_length
|
47
|
+
member = Converter.ruby_to_object(v,
|
48
|
+
max_container_size: max_container_size,
|
49
|
+
max_container_depth: (max_container_depth - 1 if max_container_depth),
|
50
|
+
max_string_length: max_string_length,
|
51
|
+
coerce: coerce)
|
52
|
+
kv_res = LibDDWAF.ddwaf_object_map_addl(obj, k.to_s, k.to_s.bytesize, member)
|
53
|
+
unless kv_res
|
54
|
+
raise LibDDWAF::Error, "Could not add to map object: #{k.inspect} => #{v.inspect}"
|
55
|
+
end
|
56
|
+
|
57
|
+
break val if max_index && i >= max_index
|
58
|
+
end unless max_container_depth == 0
|
59
|
+
|
60
|
+
obj
|
61
|
+
when String
|
62
|
+
obj = LibDDWAF::Object.new
|
63
|
+
encoded_val = val.to_s.encode('utf-8', invalid: :replace, undef: :replace)
|
64
|
+
val = encoded_val[0, max_string_length] if max_string_length
|
65
|
+
str = val.to_s
|
66
|
+
res = LibDDWAF.ddwaf_object_stringl(obj, str, str.bytesize)
|
67
|
+
if res.null?
|
68
|
+
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
69
|
+
end
|
70
|
+
|
71
|
+
obj
|
72
|
+
when Symbol
|
73
|
+
obj = LibDDWAF::Object.new
|
74
|
+
val = val.to_s[0, max_string_length] if max_string_length
|
75
|
+
str = val.to_s
|
76
|
+
res = LibDDWAF.ddwaf_object_stringl(obj, str, str.bytesize)
|
77
|
+
if res.null?
|
78
|
+
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
79
|
+
end
|
80
|
+
|
81
|
+
obj
|
82
|
+
when Integer
|
83
|
+
obj = LibDDWAF::Object.new
|
84
|
+
res = if coerce
|
85
|
+
LibDDWAF.ddwaf_object_string(obj, val.to_s)
|
86
|
+
elsif val < 0
|
87
|
+
LibDDWAF.ddwaf_object_signed(obj, val)
|
88
|
+
else
|
89
|
+
LibDDWAF.ddwaf_object_unsigned(obj, val)
|
90
|
+
end
|
91
|
+
if res.null?
|
92
|
+
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
93
|
+
end
|
94
|
+
|
95
|
+
obj
|
96
|
+
when Float
|
97
|
+
obj = LibDDWAF::Object.new
|
98
|
+
res = if coerce
|
99
|
+
LibDDWAF.ddwaf_object_string(obj, val.to_s)
|
100
|
+
else
|
101
|
+
LibDDWAF.ddwaf_object_float(obj, val)
|
102
|
+
end
|
103
|
+
if res.null?
|
104
|
+
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
105
|
+
end
|
106
|
+
|
107
|
+
obj
|
108
|
+
when TrueClass, FalseClass
|
109
|
+
obj = LibDDWAF::Object.new
|
110
|
+
res = if coerce
|
111
|
+
LibDDWAF.ddwaf_object_string(obj, val.to_s)
|
112
|
+
else
|
113
|
+
LibDDWAF.ddwaf_object_bool(obj, val)
|
114
|
+
end
|
115
|
+
if res.null?
|
116
|
+
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
117
|
+
end
|
118
|
+
|
119
|
+
obj
|
120
|
+
when NilClass
|
121
|
+
obj = LibDDWAF::Object.new
|
122
|
+
res = if coerce
|
123
|
+
LibDDWAF.ddwaf_object_string(obj, '')
|
124
|
+
else
|
125
|
+
LibDDWAF.ddwaf_object_null(obj)
|
126
|
+
end
|
127
|
+
if res.null?
|
128
|
+
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
129
|
+
end
|
130
|
+
|
131
|
+
obj
|
132
|
+
else
|
133
|
+
Converter.ruby_to_object('')
|
134
|
+
end
|
135
|
+
end
|
136
|
+
# rubocop:enable Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
137
|
+
|
138
|
+
def object_to_ruby(obj)
|
139
|
+
case obj[:type]
|
140
|
+
when :ddwaf_obj_invalid, :ddwaf_obj_null
|
141
|
+
nil
|
142
|
+
when :ddwaf_obj_bool
|
143
|
+
obj[:valueUnion][:boolean]
|
144
|
+
when :ddwaf_obj_string
|
145
|
+
obj[:valueUnion][:stringValue].read_bytes(obj[:nbEntries])
|
146
|
+
when :ddwaf_obj_signed
|
147
|
+
obj[:valueUnion][:intValue]
|
148
|
+
when :ddwaf_obj_unsigned
|
149
|
+
obj[:valueUnion][:uintValue]
|
150
|
+
when :ddwaf_obj_float
|
151
|
+
obj[:valueUnion][:f64]
|
152
|
+
when :ddwaf_obj_array
|
153
|
+
(0...obj[:nbEntries]).each.with_object([]) do |i, a|
|
154
|
+
ptr = obj[:valueUnion][:array] + i * LibDDWAF::Object.size
|
155
|
+
e = Converter.object_to_ruby(LibDDWAF::Object.new(ptr))
|
156
|
+
a << e # steep:ignore
|
157
|
+
end
|
158
|
+
when :ddwaf_obj_map
|
159
|
+
(0...obj[:nbEntries]).each.with_object({}) do |i, h|
|
160
|
+
ptr = obj[:valueUnion][:array] + i * Datadog::AppSec::WAF::LibDDWAF::Object.size
|
161
|
+
o = Datadog::AppSec::WAF::LibDDWAF::Object.new(ptr)
|
162
|
+
l = o[:parameterNameLength]
|
163
|
+
k = o[:parameterName].read_bytes(l)
|
164
|
+
v = Converter.object_to_ruby(LibDDWAF::Object.new(ptr))
|
165
|
+
h[k] = v # steep:ignore
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|