oso-oso 0.14.0 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e2aee8d8308beb5cb906dff373ef43f8a90c5d3f
4
- data.tar.gz: a121f6f4b7534f53934f49aab4e634cbbbe7f0db
3
+ metadata.gz: 32e04bc53de8b9a2a8820365219be2b0e345e765
4
+ data.tar.gz: 911eea4f97fe5aba8cb0f97485e7c9c86c68772e
5
5
  SHA512:
6
- metadata.gz: 6cb9212a01eaa50005a5d3923632741cfbbfff8c28c42a3c7f30b2cf6bf6aeba58fbe4f4c87ff3ccb43deb21dfd2db6e3f95ce7aded5996fe2eb6cb74d5de162
7
- data.tar.gz: ef8ec9735a3aba0c18d9da63ea0fda8b36e1d6c6cd3306611b1b126d6587f1381b2e558680058c4c926ed9d736b7fa21c96f92ae179b0df485d24ea3bd1c1791
6
+ metadata.gz: 70a6be55d3f0291aa53ff067dfdeea504cd261b40f2aeb4c613887c78fb7cf8d86de91e34f169c2e1198fa0f1c49a999dda8d4d608b9e61ca3011cb72925a8cf
7
+ data.tar.gz: e23bca87576a43d12e54d4206fbb50595f4bc6d8c0c06eb7a090c2fad5978c3a5f63f851d974ec5ec2469f6b9b20246826c58f29654d34ea5fe5fa8ef197d6cd
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- oso-oso (0.14.0)
4
+ oso-oso (0.15.1)
5
5
  ffi (~> 1.0)
6
6
 
7
7
  GEM
Binary file
Binary file
Binary file
@@ -24,7 +24,7 @@ module Oso
24
24
  #
25
25
  # @return [::Oso::Polar::Error] if there's an FFI error.
26
26
  # @return [::Oso::Polar::FFIErrorNotFound] if there isn't one.
27
- def self.get # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
27
+ def self.get(enrich_message) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
28
28
  error = Rust.get
29
29
  return ::Oso::Polar::FFIErrorNotFound if error.null?
30
30
 
@@ -40,6 +40,13 @@ module Oso
40
40
  subkind, details = nil
41
41
  end
42
42
 
43
+ # Enrich error message and stack trace
44
+ msg = enrich_message.call(msg) if msg
45
+ if details
46
+ details['stack_trace'] = enrich_message.call(details['stack_trace']) if details['stack_trace']
47
+ details['msg'] = enrich_message.call(details['msg']) if details['msg']
48
+ end
49
+
43
50
  case kind
44
51
  when 'Parse'
45
52
  parse_error(subkind, msg: msg, details: details)
@@ -19,10 +19,11 @@ module Oso
19
19
  attach_function :free, :string_free, [Message], :int32
20
20
  end
21
21
 
22
- def process
22
+ def process(enrich_message)
23
23
  message = JSON.parse(to_s)
24
24
  kind = message['kind']
25
25
  msg = message['msg']
26
+ msg = enrich_message.call(msg)
26
27
 
27
28
  case kind
28
29
  when 'Print'
@@ -7,6 +7,8 @@ module Oso
7
7
  module FFI
8
8
  # Wrapper class for Polar FFI pointer + operations.
9
9
  class Polar < ::FFI::AutoPointer
10
+ attr_accessor :enrich_message
11
+
10
12
  Rust = Module.new do
11
13
  extend ::FFI::Library
12
14
  ffi_lib FFI::LIB_PATH
@@ -30,7 +32,7 @@ module Oso
30
32
  # @raise [FFI::Error] if the FFI call returns an error.
31
33
  def self.create
32
34
  polar = Rust.new
33
- raise FFI::Error.get if polar.null?
35
+ handle_error if polar.null?
34
36
 
35
37
  polar
36
38
  end
@@ -39,14 +41,14 @@ module Oso
39
41
  def enable_roles
40
42
  result = Rust.enable_roles(self)
41
43
  process_messages
42
- raise FFI::Error.get if result.zero?
44
+ handle_error if result.zero?
43
45
  end
44
46
 
45
47
  # @raise [FFI::Error] if the FFI call returns an error.
46
48
  def validate_roles_config(config)
47
49
  result = Rust.validate_roles_config(self, JSON.dump(config))
48
50
  process_messages
49
- raise FFI::Error.get if result.zero?
51
+ handle_error if result.zero?
50
52
  end
51
53
 
52
54
  # @param src [String]
@@ -55,14 +57,14 @@ module Oso
55
57
  def load(src, filename: nil)
56
58
  loaded = Rust.load(self, src, filename)
57
59
  process_messages
58
- raise FFI::Error.get if loaded.zero?
60
+ handle_error if loaded.zero?
59
61
  end
60
62
 
61
63
  # @raise [FFI::Error] if the FFI call returns an error.
62
64
  def clear_rules
63
65
  cleared = Rust.clear_rules(self)
64
66
  process_messages
65
- raise FFI::Error.get if cleared.zero?
67
+ handle_error if cleared.zero?
66
68
  end
67
69
 
68
70
  # @return [FFI::Query] if there are remaining inline queries.
@@ -80,7 +82,7 @@ module Oso
80
82
  id = Rust.new_id(self)
81
83
  # TODO(gj): I don't think this error check is correct. If getting a new ID fails on the
82
84
  # Rust side, it'll probably surface as a panic (e.g., the KB lock is poisoned).
83
- raise FFI::Error.get if id.zero?
85
+ handle_error if id.zero?
84
86
 
85
87
  id
86
88
  end
@@ -91,7 +93,7 @@ module Oso
91
93
  def new_query_from_str(str)
92
94
  query = Rust.new_query_from_str(self, str, 0)
93
95
  process_messages
94
- raise FFI::Error.get if query.null?
96
+ handle_error if query.null?
95
97
 
96
98
  query
97
99
  end
@@ -102,7 +104,7 @@ module Oso
102
104
  def new_query_from_term(term)
103
105
  query = Rust.new_query_from_term(self, JSON.dump(term), 0)
104
106
  process_messages
105
- raise FFI::Error.get if query.null?
107
+ handle_error if query.null?
106
108
 
107
109
  query
108
110
  end
@@ -112,7 +114,7 @@ module Oso
112
114
  # @raise [FFI::Error] if the FFI call returns an error.
113
115
  def register_constant(value, name:)
114
116
  registered = Rust.register_constant(self, name, JSON.dump(value))
115
- raise FFI::Error.get if registered.zero?
117
+ handle_error if registered.zero?
116
118
  end
117
119
 
118
120
  def next_message
@@ -124,9 +126,13 @@ module Oso
124
126
  message = next_message
125
127
  break if message.null?
126
128
 
127
- message.process
129
+ message.process(enrich_message)
128
130
  end
129
131
  end
132
+
133
+ def handle_error
134
+ raise FFI::Error.get(enrich_message)
135
+ end
130
136
  end
131
137
  end
132
138
  end
@@ -7,6 +7,8 @@ module Oso
7
7
  module FFI
8
8
  # Wrapper class for Query FFI pointer + operations.
9
9
  class Query < ::FFI::AutoPointer
10
+ attr_accessor :enrich_message
11
+
10
12
  Rust = Module.new do
11
13
  extend ::FFI::Library
12
14
  ffi_lib FFI::LIB_PATH
@@ -27,7 +29,7 @@ module Oso
27
29
  def debug_command(cmd)
28
30
  res = Rust.debug_command(self, cmd)
29
31
  process_messages
30
- raise FFI::Error.get if res.zero?
32
+ handle_error if res.zero?
31
33
  end
32
34
 
33
35
  # @param result [String]
@@ -35,7 +37,7 @@ module Oso
35
37
  # @raise [FFI::Error] if the FFI call returns an error.
36
38
  def call_result(result, call_id:)
37
39
  res = Rust.call_result(self, call_id, result)
38
- raise FFI::Error.get if res.zero?
40
+ handle_error if res.zero?
39
41
  end
40
42
 
41
43
  # @param result [Boolean]
@@ -44,7 +46,7 @@ module Oso
44
46
  def question_result(result, call_id:)
45
47
  result = result ? 1 : 0
46
48
  res = Rust.question_result(self, call_id, result)
47
- raise FFI::Error.get if res.zero?
49
+ handle_error if res.zero?
48
50
  end
49
51
 
50
52
  # @param result [Boolean]
@@ -52,7 +54,7 @@ module Oso
52
54
  # @raise [FFI::Error] if the FFI call returns an error.
53
55
  def application_error(message)
54
56
  res = Rust.application_error(self, message)
55
- raise FFI::Error.get if res.zero?
57
+ handle_error if res.zero?
56
58
  end
57
59
 
58
60
  # @return [::Oso::Polar::QueryEvent]
@@ -60,7 +62,7 @@ module Oso
60
62
  def next_event
61
63
  event = Rust.next_event(self)
62
64
  process_messages
63
- raise FFI::Error.get if event.null?
65
+ handle_error if event.null?
64
66
 
65
67
  ::Oso::Polar::QueryEvent.new(JSON.parse(event.to_s))
66
68
  end
@@ -74,7 +76,7 @@ module Oso
74
76
  message = next_message
75
77
  break if message.null?
76
78
 
77
- message.process
79
+ message.process(enrich_message)
78
80
  end
79
81
  end
80
82
 
@@ -82,10 +84,14 @@ module Oso
82
84
  # @raise [FFI::Error] if the FFI call returns an error.
83
85
  def source
84
86
  res = Rust.source(self)
85
- raise FFI::Error.get if res.null?
87
+ handle_error if res.null?
86
88
 
87
89
  res.to_s
88
90
  end
91
+
92
+ def handle_error
93
+ raise FFI::Error.get(enrich_message)
94
+ end
89
95
  end
90
96
  end
91
97
  end
@@ -149,6 +149,33 @@ module Oso
149
149
  raise PolarRuntimeError, "Error constructing instance of #{cls_name}: #{e}"
150
150
  end
151
151
 
152
+ OPS = {
153
+ 'Lt' => :<,
154
+ 'Gt' => :>,
155
+ 'Eq' => :==,
156
+ 'Geq' => :>=,
157
+ 'Leq' => :<=,
158
+ 'Neq' => :!=
159
+ }.freeze
160
+
161
+ # Compare two values
162
+ #
163
+ # @param op [String] operation to perform.
164
+ # @param args [Array<Object>] left and right args to operation.
165
+ # @raise [PolarRuntimeError] if operation fails or is unsupported.
166
+ # @return [Boolean]
167
+ def operator(operation, args)
168
+ left, right = args
169
+ op = OPS[operation]
170
+ raise PolarRuntimeError, "Unsupported external operation '#{left.class} #{operation} #{right.class}'" if op.nil?
171
+
172
+ begin
173
+ left.__send__ op, right
174
+ rescue StandardError
175
+ raise PolarRuntimeError, "External operation '#{left.class} #{operation} #{right.class}' failed."
176
+ end
177
+ end
178
+
152
179
  # Check if the left class is more specific than the right class
153
180
  # with respect to the given instance.
154
181
  #
@@ -174,17 +201,6 @@ module Oso
174
201
  instance.is_a? cls
175
202
  end
176
203
 
177
- # Check if two instances unify
178
- #
179
- # @param left_instance_id [Integer]
180
- # @param right_instance_id [Integer]
181
- # @return [Boolean]
182
- def unify?(left_instance_id, right_instance_id)
183
- left_instance = get_instance(left_instance_id)
184
- right_instance = get_instance(right_instance_id)
185
- left_instance == right_instance
186
- end
187
-
188
204
  # Turn a Ruby value into a Polar term that's ready to be sent across the
189
205
  # FFI boundary.
190
206
  #
@@ -226,7 +242,7 @@ module Oso
226
242
  { 'Pattern' => { 'Instance' => { 'tag' => value.tag, 'fields' => dict['Dictionary'] } } }
227
243
  end
228
244
  else
229
- { 'ExternalInstance' => { 'instance_id' => cache_instance(value), 'repr' => value.to_s } }
245
+ { 'ExternalInstance' => { 'instance_id' => cache_instance(value), 'repr' => nil } }
230
246
  end
231
247
  { 'value' => value }
232
248
  end
@@ -292,6 +308,12 @@ module Oso
292
308
  raise UnexpectedPolarTypeError, tag
293
309
  end
294
310
  end
311
+
312
+ def enrich_message(msg)
313
+ msg.gsub(/\^\{id: ([0-9]+)\}/) do
314
+ get_instance(Regexp.last_match[1].to_i).to_s
315
+ end
316
+ end
295
317
  end
296
318
  end
297
319
  end
@@ -34,9 +34,10 @@ module Oso
34
34
  # @return [Host]
35
35
  attr_reader :host
36
36
 
37
- def initialize
37
+ def initialize # rubocop:disable Metrics/MethodLength
38
38
  @ffi_polar = FFI::Polar.create
39
39
  @host = Host.new(ffi_polar)
40
+ @ffi_polar.enrich_message = @host.method(:enrich_message)
40
41
  @polar_roles_enabled = false
41
42
 
42
43
  # Register global constants.
@@ -13,6 +13,7 @@ module Oso
13
13
  def initialize(ffi_query, host:)
14
14
  @calls = {}
15
15
  @ffi_query = ffi_query
16
+ ffi_query.enrich_message = host.method(:enrich_message)
16
17
  @host = host
17
18
  end
18
19
 
@@ -146,13 +147,12 @@ module Oso
146
147
  class_tag = event.data['class_tag']
147
148
  answer = host.isa?(instance, class_tag: class_tag)
148
149
  question_result(answer, call_id: event.data['call_id'])
149
- when 'ExternalUnify'
150
- left_instance_id = event.data['left_instance_id']
151
- right_instance_id = event.data['right_instance_id']
152
- answer = host.unify?(left_instance_id, right_instance_id)
153
- question_result(answer, call_id: event.data['call_id'])
154
150
  when 'Debug'
155
- puts event.data['message'] if event.data['message']
151
+ msg = event.data['message']
152
+ if msg
153
+ msg = host.enrich_message(msg) if msg
154
+ puts msg
155
+ end
156
156
  print 'debug> '
157
157
  begin
158
158
  input = $stdin.readline.chomp.chomp(';')
@@ -162,7 +162,10 @@ module Oso
162
162
  command = JSON.dump(host.to_polar(input))
163
163
  ffi_query.debug_command(command)
164
164
  when 'ExternalOp'
165
- raise UnimplementedOperationError, 'comparison operators'
165
+ op = event.data['operator']
166
+ args = event.data['args'].map(&host.method(:to_ruby))
167
+ answer = host.operator(op, args)
168
+ question_result(answer, call_id: event.data['call_id'])
166
169
  when 'NextExternal'
167
170
  call_id = event.data['call_id']
168
171
  iterable = event.data['iterable']
data/lib/oso/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Oso
4
- VERSION = '0.14.0'
4
+ VERSION = '0.15.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oso-oso
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oso Security, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-16 00:00:00.000000000 Z
11
+ date: 2021-09-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi