From 02b65a500f8dd89caf2b13ae066dbb4b7e1b5e3c Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sat, 17 Jun 2017 22:01:16 +0300 Subject: [PATCH] Proper boundary checks & tests for them --- XS.xs | 27 +++++++++++---------------- t/Algorithm-BIT-XS.t | 13 ++++++++++--- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/XS.xs b/XS.xs index 3e6c839..bc8d890 100644 --- a/XS.xs +++ b/XS.xs @@ -5,6 +5,11 @@ #include "ppport.h" +#define CHECK_INDEX(idx, min, max, ret) if(idx < min || idx > max) { \ + croak("Index not in range [" IVdf "," IVdf "]", (IV)(min), (IV)(max)); \ + return ret; \ + } + typedef struct { IV n; IV* t; @@ -29,10 +34,7 @@ void bit_free(bit *b) { } IV bit_query(bit *b, IV idx) { - if(idx > b->n || idx < 1){ - croak("Index not in range [1," IVdf "]", b->n); - return 0; - } + CHECK_INDEX(idx, 0, b->n - 1, 0); IV ret = 0; while(idx) ret += b->t[idx], idx -= idx & -idx; @@ -40,10 +42,7 @@ IV bit_query(bit *b, IV idx) { } void bit_update(bit *b, IV idx, IV value) { - if(idx > b->n || idx < 1){ - croak("Index not in range [1," IVdf "]", b->n); - return; - } + CHECK_INDEX(idx, 0, b->n - 1, ); while(idx < b->n) b->t[idx] += value, idx += idx & -idx; } @@ -77,6 +76,8 @@ void bit2d_free(bit2d *b) { } IV bit2d_query(bit2d *b, IV i1, IV i2) { + CHECK_INDEX(i1, 1, b->n - 1, 0); + CHECK_INDEX(i2, 1, b->m - 1, 0); if(i1 > b->n || i1 < 1) { croak("Index 1 not in range [1," IVdf "]", b->n); return 0; @@ -96,14 +97,8 @@ IV bit2d_query(bit2d *b, IV i1, IV i2) { } void bit2d_update(bit2d *b, IV i1, IV i2, IV value) { - if(i1 > b->n || i1 < 1) { - croak("Index 1 not in range [1," IVdf "]", b->n); - return; - } - if(i2 > b->m || i2 < 1) { - croak("Index 2 not in range [1," IVdf "]", b->m); - return; - } + CHECK_INDEX(i1, 1, b->n - 1, ); + CHECK_INDEX(i2, 1, b->m - 1, ); IV i2c = i2; while(i1 < b->n) { i2 = i2c; diff --git a/t/Algorithm-BIT-XS.t b/t/Algorithm-BIT-XS.t index c2ee47a..914792a 100644 --- a/t/Algorithm-BIT-XS.t +++ b/t/Algorithm-BIT-XS.t @@ -2,11 +2,13 @@ use strict; use warnings; -use Test::More tests => 17; +use Test::More tests => 24; BEGIN { use_ok('Algorithm::BIT::XS') }; BEGIN { use_ok('Algorithm::BIT2D::XS') }; -my $bit = Algorithm::BIT::XS->new(100); +my $bit = Algorithm::BIT::XS->new(25); +ok !eval{$bit->query(26); 1}, 'query(26) fails'; +ok !eval{$bit->update(26, 5); 1}, 'update(26, 5) fails'; is $bit->query(5), 0; $bit->update(4, 2); $bit->update(5, 3); @@ -14,6 +16,7 @@ is $bit->query(3), 0; is $bit->query(4), 2; is $bit->query(5), 5; is $bit->query(6), 5; +is $bit->query(0), 0; $bit->update(5, -3); is $bit->query(5), 2; @@ -32,7 +35,11 @@ is $bit->query(15), 0; is $bit->query(16), 10; -my $bit2d = Algorithm::BIT2D::XS->new(100, 50); +my $bit2d = Algorithm::BIT2D::XS->new(10, 5); +ok !eval{$bit2d->query(11, 5); 1}, 'query(11, 5) fails'; +ok !eval{$bit2d->query(10, 6); 1}, 'query(10, 6) fails'; +ok !eval{$bit2d->update(11, 5, 2); 1}, 'update(11, 5, 2) fails'; +ok !eval{$bit2d->update(10, 6, 2); 1}, 'update(10, 6, 2) fails'; is $bit2d->query(5, 5), 0; $bit2d->update(4, 4, 2); $bit2d->update(5, 1, 3); -- 2.30.2