Skip to content

Commit f0496ad

Browse files
committed
Check that advisory lock prefix fits inside four bytes
Add an extra safety check that an advisory lock prefix fits inside of four bytes, which is all that's reserved for one.
1 parent 94aca9b commit f0496ad

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

lib/client.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module River
2626
class Client
2727
def initialize(driver, advisory_lock_prefix: nil)
2828
@driver = driver
29-
@advisory_lock_prefix = advisory_lock_prefix
29+
@advisory_lock_prefix = self.check_advisory_lock_prefix_bounds(advisory_lock_prefix)
3030
@time_now_utc = -> { Time.now.utc } # for test time stubbing
3131
end
3232

@@ -137,6 +137,16 @@ def insert_many(args)
137137
@driver.job_insert_many(all_params)
138138
end
139139

140+
private def check_advisory_lock_prefix_bounds(advisory_lock_prefix)
141+
return nil if advisory_lock_prefix.nil?
142+
143+
# 2**32-1 is 0xffffffff (the largest number that's four bytes)
144+
if advisory_lock_prefix < 0 || advisory_lock_prefix > 2**32-1
145+
raise ArgumentError, "advisory lock prefix must fit inside four bytes"
146+
end
147+
advisory_lock_prefix
148+
end
149+
140150
# Default states that are used during a unique insert. Can be overridden by
141151
# setting UniqueOpts#by_state.
142152
DEFAULT_UNIQUE_STATES = [

sig/client.rbs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ module River
88
@driver: _Driver
99
@time_now_utc: ^() -> Time
1010

11-
DEFAULT_UNIQUE_STATES: Array[jobStateAll]
12-
EMPTY_INSERT_OPTS: InsertOpts
13-
1411
def initialize: (_Driver driver, ?advisory_lock_prefix: Integer?) -> void
1512
def insert: (jobArgs, ?insert_opts: InsertOpts) -> InsertResult
1613
def insert_many: (Array[jobArgs | InsertManyParams]) -> Integer
1714

15+
private def check_advisory_lock_prefix_bounds: (Integer?) -> Integer?
16+
17+
DEFAULT_UNIQUE_STATES: Array[jobStateAll]
18+
EMPTY_INSERT_OPTS: InsertOpts
19+
1820
private def check_unique_job: (Driver::JobInsertParams, UniqueOpts?) { () -> InsertResult } -> InsertResult
1921
private def make_insert_params: (jobArgs, InsertOpts, ?is_insert_many: bool) -> [Driver::JobInsertParams, UniqueOpts?]
2022
private def truncate_time: (Time, Integer) -> Time

spec/client_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,22 @@ class SimpleArgsWithInsertOpts < SimpleArgs
173173
)
174174
end
175175

176+
it "errors if advisory lock prefix is larger than four bytes" do
177+
River::Client.new(mock_driver, advisory_lock_prefix: 123)
178+
179+
expect do
180+
River::Client.new(mock_driver, advisory_lock_prefix: -1)
181+
end.to raise_error(ArgumentError, "advisory lock prefix must fit inside four bytes")
182+
183+
# 2^32-1 is 0xffffffff (1s for 32 bits) which fits
184+
River::Client.new(mock_driver, advisory_lock_prefix: 2**32-1)
185+
186+
# 2^32 is 0x100000000, which does not
187+
expect do
188+
River::Client.new(mock_driver, advisory_lock_prefix: 2**32)
189+
end.to raise_error(ArgumentError, "advisory lock prefix must fit inside four bytes")
190+
end
191+
176192
it "errors if args don't respond to #kind" do
177193
args_klass = Class.new do
178194
def to_json = {}

0 commit comments

Comments
 (0)