Proper boundary checks & tests for them
authorMarius Gavrilescu <marius@ieval.ro>
Sat, 17 Jun 2017 19:01:16 +0000 (22:01 +0300)
committerMarius Gavrilescu <marius@ieval.ro>
Sat, 17 Jun 2017 19:01:16 +0000 (22:01 +0300)
XS.xs
t/Algorithm-BIT-XS.t

diff --git a/XS.xs b/XS.xs
index 3e6c839e892099d38902dbf91c1c70fe5c8c522c..bc8d89005e655c4a2187b2aaa8a0b95d8c2437b3 100644 (file)
--- 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;
index c2ee47a3cee96a3c35df85d77af74a37722d69ae..914792a9c0780c375a27e3c05be2cabd36b43255 100644 (file)
@@ -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);
This page took 0.013104 seconds and 4 git commands to generate.