Skip to content

Commit

Permalink
Handle low-level libddwaf exception in Context
Browse files Browse the repository at this point in the history
  • Loading branch information
Strech committed Oct 29, 2024
1 parent 7f64645 commit 2cb89c0
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 7 deletions.
21 changes: 15 additions & 6 deletions lib/datadog/appsec/processor/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def initialize(handle, telemetry:)
@events = []
@run_mutex = Mutex.new

@libddwaf_tag = "libddwaf:#{WAF::VERSION::STRING}"
@libddwaf_debug_tag = "libddwaf:#{WAF::VERSION::STRING}"
end

def run(input, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
Expand All @@ -35,7 +35,7 @@ def run(input, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
v.nil? ? true : v.empty?
end

_code, result = @context.run(input, timeout)
_code, result = try_run(input, timeout)

stop_ns = Core::Utils::Time.get_time(:nanosecond)

Expand All @@ -59,7 +59,7 @@ def extract_schema
}
}

_code, result = @context.run(input, WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
_code, result = try_run(input, WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)

report_execution(result)
result
Expand All @@ -71,13 +71,22 @@ def finalize

private

def try_run(input, timeout)
@context.run(input, timeout)
rescue WAF::LibDDWAF::Error => e
Datadog.logger.debug { "#{@libddwaf_debug_tag} execution error: #{e} backtrace: #{e.backtrace&.first(3)}" }
@telemetry.report(e, description: 'libddwaf internal low-level error')

[:err_internal, WAF::Result.new(:err_internal, [], 0.0, false, [], [])]
end

def report_execution(result)
Datadog.logger.debug { "#{@libddwaf_tag} execution timed out: #{result.inspect}" } if result.timeout
Datadog.logger.debug { "#{@libddwaf_debug_tag} execution timed out: #{result.inspect}" } if result.timeout

if LIBDDWAF_SUCCESSFUL_EXECUTION_CODES.include?(result.status)
Datadog.logger.debug { "#{@libddwaf_tag} execution result: #{result.inspect}" }
Datadog.logger.debug { "#{@libddwaf_debug_tag} execution result: #{result.inspect}" }
else
message = "#{@libddwaf_tag} execution error: #{result.status.inspect}"
message = "#{@libddwaf_debug_tag} execution error: #{result.status.inspect}"

Datadog.logger.debug { message }
@telemetry.error(message)
Expand Down
4 changes: 3 additions & 1 deletion sig/datadog/appsec/processor/context.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Datadog

@run_mutex: ::Thread::Mutex

@libddwaf_tag: ::String
@libddwaf_debug_tag: ::String

LIBDDWAF_SUCCESSFUL_EXECUTION_CODES: ::Array[::Symbol]

Expand All @@ -38,6 +38,8 @@ module Datadog

private

def try_run: (Hash[untyped, untyped] input, ::Integer timeout) -> [::Symbol, WAF::Result]

def report_execution: (WAF::Result result) -> void

def extract_schema?: () -> bool
Expand Down
17 changes: 17 additions & 0 deletions spec/datadog/appsec/processor/context_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,23 @@
context.run(input, timeout)
end
end

context 'run failed with libddwaf low-level exception' do
before do
allow(context.instance_variable_get(:@context)).to receive(:run).with(input, timeout)
.and_raise(Datadog::AppSec::WAF::LibDDWAF::Error, 'Could not convert persistent data')
end

let(:result) { context.run(input, timeout) }

it 'sends telemetry report' do
expect(telemetry).to receive(:error).with(/libddwaf:[\d.]+ execution error: :err_invalid_object/)
expect(telemetry).to receive(:report)
.with(kind_of(Datadog::AppSec::WAF::LibDDWAF::Error), description: 'libddwaf internal low-level error')

expect(result.status).to eq(:err_internal)
end
end
end

describe '#extract_schema' do
Expand Down

0 comments on commit 2cb89c0

Please sign in to comment.