]> git.vpit.fr Git - perl/modules/Scalar-Vec-Util.git/commitdiff
Improve argument checking
authorVincent Pit <vince@profvince.com>
Sun, 17 May 2009 17:36:28 +0000 (19:36 +0200)
committerVincent Pit <vince@profvince.com>
Sun, 17 May 2009 17:36:28 +0000 (19:36 +0200)
undef arguments are now allowed. Signedness is checked. Functions have prototypes.

Util.xs
lib/Scalar/Vec/Util.pm
t/10-veq-pp.t
t/11-veq.t
t/20-vfill-pp.t
t/21-vfill.t
t/30-vcopy-pp.t
t/31-vcopy-copy.t
t/40-vshift.t
t/50-vrot.t

diff --git a/Util.xs b/Util.xs
index 75ba8cabcabc72fd469c12eb9ceb36381c39f15e..013bea280d069f0caf3f4c6bdeff44a086a48e30 100644 (file)
--- a/Util.xs
+++ b/Util.xs
 
 #include "bitvect.h"
 
-STATIC const char svu_error_invarg[] = "Invalid argument";
+STATIC void svu_validate_uv(pTHX_ SV *sv, size_t *offset, const char *desc) {
+#define svu_validate_uv(S, O, D) svu_validate_uv(aTHX_ (S), (O), (D))
+ IV i;
+
+ if (SvOK(sv) && SvIOK(sv)) {
+  if (SvIsUV(sv))
+   *offset = SvUVX(sv);
+  else {
+   i = SvIVX(sv);
+   if (i < 0)
+    goto fail;
+   *offset = i;
+  }
+ } else {
+  i = SvIV(sv);
+  if (i < 0)
+   goto fail;
+  *offset = i;
+ }
+
+ return;
+
+fail:
+ *offset = 0;
+ croak("Invalid negative %s", desc ? desc : "integer");
+}
 
 /* --- XS ------------------------------------------------------------------ */
 
@@ -33,13 +58,10 @@ PREINIT:
  size_t s, l, n, o;
  char f, *v;
 CODE:
- if (!SvOK(sv) || !SvOK(ss) || !SvOK(sl) || !SvOK(sf))
-  croak(svu_error_invarg);
-
- l = SvUV(sl);
+ svu_validate_uv(sl, &l, "length");
  if (!l)
   XSRETURN(0);
- s = SvUV(ss);
+ svu_validate_uv(ss, &s, "offset");
  f = SvTRUE(sf);
  SvUPGRADE(sv, SVt_PV);
 
@@ -65,14 +87,11 @@ PREINIT:
  size_t fs, ts, l, lf = 0, n, o;
  char *t, *f;
 CODE:
- if (!SvOK(sf) || !SvOK(sfs) || !SvOK(st) || !SvOK(sts) || !SvOK(sl))
-  croak(svu_error_invarg);
-
- l  = SvUV(sl);
+ svu_validate_uv(sl, &l, "length");
  if (!l)
   XSRETURN(0);
fs = SvUV(sfs);
ts = SvUV(sts);
svu_validate_uv(sfs, &fs, "offset");
svu_validate_uv(sts, &ts, "offset");
  SvUPGRADE(sf, SVt_PV);
  SvUPGRADE(st, SVt_PV);
 
@@ -114,14 +133,11 @@ PREINIT:
  size_t s1, s2, l, o, n;
  char *v1, *v2;
 CODE:
- if (!SvOK(sv1) || !SvOK(ss1) || !SvOK(sv2) || !SvOK(ss2) || !SvOK(sl))
-  croak(svu_error_invarg);
-
- l  = SvUV(sl);
+ svu_validate_uv(sl, &l, "length");
  if (!l)
-  XSRETURN(0);
- s1 = SvUV(ss1);
- s2 = SvUV(ss2);
+  XSRETURN_YES;
+ svu_validate_uv(ss1, &s1, "offset");
+ svu_validate_uv(ss2, &s2, "offset");
  SvUPGRADE(sv1, SVt_PV);
  SvUPGRADE(sv2, SVt_PV);
 
index b7ab6ab774e36fc5452c33a85c98e2dca08e3eb4..da9f033e18c423cdfc27867ecdd4150e8c0bc6c3 100644 (file)
@@ -72,15 +72,11 @@ Grows C<$vec> if necessary.
 
 =cut
 
-sub _alldef {
- for (@_) { return 0 unless defined }
- return 1;
-}
-
 sub vfill_pp ($$$$) {
- (undef, my $s, my $l, my $x) = @_;
- croak "Invalid argument" unless _alldef @_;
+ my ($s, $l, $x) = @_[1 .. 3];
  return unless $l;
+ croak 'Invalid negative offset' if $s < 0;
+ croak 'Invalid negative length' if $l < 0;
  $x = ~0 if $x;
  my $SIZE = 32;
  my $t = int($s / $SIZE) + 1;
@@ -105,8 +101,9 @@ Doesn't need to allocate any extra memory.
 
 sub vcopy_pp ($$$$$) {
  my ($fs, $ts, $l) = @_[1, 3, 4];
- croak "Invalid argument" unless _alldef @_;
  return unless $l;
+ croak 'Invalid negative offset' if $fs < 0 or $ts < 0;
+ croak 'Invalid negative length' if $l  < 0;
  my $step = $ts - $fs;
  if ($step <= 0) { 
   vec($_[2], $_ + $step, 1) = vec($_[0], $_, 1) for $fs .. $fs + $l - 1;
@@ -126,7 +123,9 @@ Doesn't need to allocate any extra memory.
 
 sub vshift ($$$$;$) {
  my ($start, $length, $bits, $insert) = @_[1 .. 4];
- return unless $bits;
+ return unless $length and $bits;
+ croak 'Invalid negative offset' if $start  < 0;
+ croak 'Invalid negative length' if $length < 0;
  my $left = 1;
  if ($bits < 0) {
   $left = 0;
@@ -157,6 +156,8 @@ Currently allocates an extra buffer of size C<O($bits)>.
 sub vrot ($$$$) {
  my ($start, $length, $bits) = @_[1 .. 3];
  return unless $length and $bits;
+ croak 'Invalid negative offset' if $start  < 0;
+ croak 'Invalid negative length' if $length < 0;
  my $left = 1;
  if ($bits < 0) {
   $left = 0;
@@ -186,7 +187,8 @@ If needed, C<$length> is decreased to fit inside C<$v1> and C<$v2> boundaries.
 
 sub veq_pp ($$$$$) {
  my ($s1, $s2, $l) = @_[1, 3, 4];
- croak "Invalid argument" unless _alldef @_;
+ croak 'Invalid negative offset' if $s1 < 0 or $s2 < 0;
+ croak 'Invalid negative length' if $l  < 0;
  my $i = 0;
  while ($i < $l) {
   return 0 if vec($_[0], $s1 + $i, 1) != vec($_[2], $s2 + $i, 1);
index 98fea99ad69657588fef72c64396bc3d5b300d82..509fd98f3cba1989c96a62681e9f0e1535340961 100644 (file)
@@ -7,16 +7,12 @@ use Test::More 'no_plan';
 
 use Scalar::Vec::Util;
 
-eval { Scalar::Vec::Util::veq_pp(undef, 0, my $y, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { Scalar::Vec::Util::veq_pp(my $x, undef, my $y, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { Scalar::Vec::Util::veq_pp(my $x, 0, undef, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { Scalar::Vec::Util::veq_pp(my $x, 0, my $y, undef, 0) };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
-eval { Scalar::Vec::Util::veq_pp(my $x, 0, my $y, 0, undef) };
-like($@, qr/Invalid\s+argument/, 'fifth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 3, 'offset', '-1' ], [ 4, 'length', -1 ]) {
+ my @args  = ('1') x 5;
+ $args[$_->[0]] = $_->[2];
+ eval { &Scalar::Vec::Util::veq_pp(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
 
 my $p = 8;
 my $n = 3 * $p;
index 3d141b35c052572ac0149fb28d87cad13f238f14..31ba0a8f6780cc8a8148350db1bf91059673c135 100644 (file)
@@ -7,16 +7,12 @@ use Test::More 'no_plan';
 
 use Scalar::Vec::Util qw/veq SVU_SIZE/;
 
-eval { veq undef, 0, my $y, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { veq my $x, undef, my $y, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { veq my $x, 0, undef, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { veq my $x, 0, my $y, undef, 0 };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
-eval { veq my $x, 0, my $y, 0, undef };
-like($@, qr/Invalid\s+argument/, 'fifth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 3, 'offset', '-1' ], [ 4, 'length', -1 ]) {
+ my @args  = ('1') x 5;
+ $args[$_->[0]] = $_->[2];
+ eval { &veq(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
 
 my $p = SVU_SIZE;
 $p = 8 if $p < 8;
@@ -48,8 +44,8 @@ for my $s1 (@s) {
    pat $v1, $s1, $l, 0;
    pat $v2, $s2, $l, 0;
    ok(veq($v1 => $s1, $v2 => $s2, $l), "veq $s1, $s2, $l");
-   ok(!veq($v1 => $s1 - 1, $v2 => $s2, $l), 'not veq_pp ' . ($s1 - 1) . ", $s2, $l") if $l > 0;
-   ok(!veq($v1 => $s1 + 1, $v2 => $s2, $l), 'not veq_pp ' . ($s1 + 1) . ", $s2, $l") if $l > 0;
+   ok(!veq($v1 => $s1 - 1, $v2 => $s2, $l), 'not veq ' . ($s1 - 1) . ", $s2, $l") if $l > 0;
+   ok(!veq($v1 => $s1 + 1, $v2 => $s2, $l), 'not veq ' . ($s1 + 1) . ", $s2, $l") if $l > 0;
   }
  }
 }
index aaf3618a78f6a1c2a46a8a62124a79bfffdbaadb..3bb893d4c064e2d2992cf77dbd820f6efc3e8944 100644 (file)
@@ -7,14 +7,12 @@ use Test::More 'no_plan';
 
 use Scalar::Vec::Util;
 
-eval { Scalar::Vec::Util::vfill_pp(undef, 0, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { Scalar::Vec::Util::vfill_pp(my $x, undef, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { Scalar::Vec::Util::vfill_pp(my $x, 0, undef, 0) };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { Scalar::Vec::Util::vfill_pp(my $x, 0, 0, undef) };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 2, 'length', '-1' ]) {
+ my @args  = ('1') x 4;
+ $args[$_->[0]] = $_->[2];
+ eval { &Scalar::Vec::Util::vfill_pp(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
 
 my $p = 8;
 my $n = 3 * $p;
index 33565f954bcb9b89adee5a838ad396a25ef0019c..47026688f04636d7b9b1fed3a48acdd1e8bf7e95 100644 (file)
@@ -7,14 +7,12 @@ use Test::More 'no_plan';
 
 use Scalar::Vec::Util qw/vfill SVU_SIZE/;
 
-eval { vfill undef, 0, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { vfill my $x, undef, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { vfill my $x, 0, undef, 0 };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { vfill my $x, 0, 0, undef };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 2, 'length', '-1' ]) {
+ my @args  = (~0) x 4;
+ $args[$_->[0]] = $_->[2];
+ eval { &vfill(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
 
 my $p = SVU_SIZE;
 $p = 8 if $p < 8;
index f8f29cc5944488596892f49f76a06eae9825f314..2ce27731c773c808bb4fe053b3044cd2103a8ead 100644 (file)
@@ -7,16 +7,12 @@ use Test::More 'no_plan';
 
 use Scalar::Vec::Util qw/SVU_SIZE/;
 
-eval { Scalar::Vec::Util::vcopy_pp(undef, 0, my $y, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { Scalar::Vec::Util::vcopy_pp(my $x, undef, my $y, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { Scalar::Vec::Util::vcopy_pp(my $x, 0, undef, 0, 0) };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { Scalar::Vec::Util::vcopy_pp(my $x, 0, my $y, undef, 0) };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
-eval { Scalar::Vec::Util::vcopy_pp(my $x, 0, my $y, 0, undef) };
-like($@, qr/Invalid\s+argument/, 'fifth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 3, 'offset', '-1' ], [ 4, 'length', -1 ]) {
+ my @args  = ('1') x 5;
+ $args[$_->[0]] = $_->[2];
+ eval { &Scalar::Vec::Util::vcopy_pp(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
 
 my $p = SVU_SIZE;
 $p = 8 if $p < 8;
index 2d1132d4a5e3843525a3313990830973f4d49f76..af127f8c65c11c976f23f08cc894e3c40e528d76 100644 (file)
@@ -7,16 +7,12 @@ use Test::More 'no_plan';
 
 use Scalar::Vec::Util qw/vcopy SVU_SIZE/;
 
-eval { vcopy undef, 0, my $y, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'first argument undef croaks');
-eval { vcopy my $x, undef, my $y, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'second argument undef croaks');
-eval { vcopy my $x, 0, undef, 0, 0 };
-like($@, qr/Invalid\s+argument/, 'third argument undef croaks');
-eval { vcopy my $x, 0, my $y, undef, 0 };
-like($@, qr/Invalid\s+argument/, 'fourth argument undef croaks');
-eval { vcopy my $x, 0, my $y, 0, undef };
-like($@, qr/Invalid\s+argument/, 'fifth argument undef croaks');
+for ([ 1, 'offset', -1 ], [ 3, 'offset', '-1' ], [ 4, 'length', -1 ]) {
+ my @args  = (~0) x 5;
+ $args[$_->[0]] = $_->[2];
+ eval { &vcopy(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
 
 my $p = SVU_SIZE;
 $p = 8 if $p < 8;
index 5fe1b69feded44e87c5d534b904bc2faba27cee9..4c27c8324846b80f5837f64352718cdf8ff1e0f5 100644 (file)
@@ -7,6 +7,13 @@ use Test::More 'no_plan';
 
 use Scalar::Vec::Util qw/vshift SVU_SIZE/;
 
+for ([ 1, 'offset', -1 ], [ 2, 'length', '-1' ]) {
+ my @args  = ('1') x 4;
+ $args[$_->[0]] = $_->[2];
+ eval { &vshift(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
+
 my $p = SVU_SIZE;
 $p = 8 if $p < 8;
 my $n = 3 * $p;
index 9222ae3b6785c63eefa4f7144f410ac8d87850fa..6ce0c410000457eaacb895bfa7c6e7e5bfe815cd 100644 (file)
@@ -7,6 +7,13 @@ use Test::More 'no_plan';
 
 use Scalar::Vec::Util qw/vrot vcopy SVU_SIZE/;
 
+for ([ 1, 'offset', -1 ], [ 2, 'length', '-1' ]) {
+ my @args  = ('1') x 4;
+ $args[$_->[0]] = $_->[2];
+ eval { &vrot(@args) }; my $line = __LINE__;
+ like $@, qr/^Invalid\s+negative\s+$_->[1]\s+at\s+\Q$0\E\s+line\s+$line/;
+}
+
 my $p = SVU_SIZE;
 $p = 8 if $p < 8;
 my $n = 3 * $p;
@@ -28,6 +35,11 @@ sub pat {
 
 sub expected {
  (undef, my $s, my $l, my $b, my $left) = @_;
+ unless ($l) {
+  myfill($_[0], 0,  $s,      0);
+  myfill($_[0], $s, $n - $s, 1);
+  return;
+ }
  my $lx = int($l / 2);
  my $ly = $l - $lx;
  $b %= $l;
@@ -71,7 +83,7 @@ sub try {
  my ($left) = @_;
  my @s = ($p - $q) .. ($p + $q);
  for my $s (@s) {
-  for my $l (1 .. $n - 1) {
+  for my $l (0 .. $n - 1) {
    last if $s + $l > $n;
    my $l2 = int($l/2);
    rst $v0;