From 90c348c972f1435ccf0315ba095b0da099be20dc Mon Sep 17 00:00:00 2001 From: edmoffo Date: Sun, 24 May 2026 04:31:35 +0000 Subject: [PATCH] fix(download): #302 anchor Content-Range guard regexes with \A and \z The total-size guard at lib/baza-rb.rb:855 read /^\*|[0-9]+$/, which because of regex precedence parsed as (^\*)|([0-9]+$) and matched every string starting with `*` or ending in digits. Values like `*malformed`, `abc123`, and `-5` slipped past the guard, and the downstream total.to_i + e.to_i comparisons then either spun the loop or finished on a truncated file. The neighboring range guard at lib/baza-rb.rb:857 had the same shape with the milder `^` and `$` line anchors, which also allow a stray newline at the boundaries. The fix replaces /^\*|[0-9]+$/ with /\A(?:\*|[0-9]+)\z/ on line 855 and /^[0-9]+$/ with /\A[0-9]+\z/ on line 857, so the alternation lives under one pair of string anchors and a malformed total or end value raises the existing "Total size is not valid" / "Range is not valid" errors as the guard intended. A regression test in test/test_baza_edge.rb exercises four malformed totals against the download loop and pins the new behavior. Closes #302 --- lib/baza-rb.rb | 4 ++-- test/test_baza_edge.rb | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/baza-rb.rb b/lib/baza-rb.rb index b873eac..2cd769a 100644 --- a/lib/baza-rb.rb +++ b/lib/baza-rb.rb @@ -852,9 +852,9 @@ def download(uri, file) break if ret.code == 200 _, v = ret.headers['Content-Range'].split range, total = v.split('/') - raise "Total size is not valid (#{total.inspect})" unless total.match?(/^\*|[0-9]+$/) + raise "Total size is not valid (#{total.inspect})" unless total.match?(/\A(?:\*|[0-9]+)\z/) _b, e = range.split('-') - raise "Range is not valid (#{range.inspect})" unless e.match?(/^[0-9]+$/) + raise "Range is not valid (#{range.inspect})" unless e.match?(/\A[0-9]+\z/) len = ret.headers['Content-Length'].to_i break if e.to_i == total.to_i - 1 break if total == '0' diff --git a/test/test_baza_edge.rb b/test/test_baza_edge.rb index ce392ff..5843702 100644 --- a/test/test_baza_edge.rb +++ b/test/test_baza_edge.rb @@ -452,6 +452,29 @@ def test_lock_raises_when_owner_is_empty assert_equal('The "owner" of the lock may not be empty', error.message) end + def test_download_rejects_malformed_content_range_total + WebMock.disable_net_connect! + ['*malformed', 'abc123', '0xff', '-5'].each do |total| + Dir.mktmpdir do |dir| + file = File.join(dir, 'out.bin') + host = 'example.org' + stub_request(:get, "https://#{host}:443/file") + .with(headers: { 'Range' => 'bytes=0-' }) + .to_return( + status: 206, + body: 'first ', + headers: { 'Content-Range' => "bytes 0-5/#{total}" } + ) + baza = BazaRb.new(host, 443, '000', loog: Loog::NULL, compress: false) + error = + assert_raises(RuntimeError) do + baza.send(:download, baza.send(:home).append('file'), file) + end + assert_equal("Total size is not valid (#{total.inspect})", error.message) + end + end + end + def test_upload_switches_host_mid_chunks WebMock.disable_net_connect! Dir.mktmpdir do |dir|