String: Added boundary checks
authorArjen Baart <arjen@andromeda.nl>
Tue, 5 Nov 2019 21:07:28 +0000 (22:07 +0100)
committerArjen Baart <arjen@andromeda.nl>
Tue, 5 Nov 2019 21:07:28 +0000 (22:07 +0100)
ChangeLog
TODO
src/String.h
src/string.cpp
test/string_basics.cpp
test/string_basics.exp
test/string_substring.cpp
test/string_substring.exp

index f436736..afa2233 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+  - String: Boundary checking on index and subtring operators
   - Ported class Integer from the Gnu libg++ library.
 
 Oct 31, 2019 - Release 0.2
diff --git a/TODO b/TODO
index fea13d1..70ec276 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,7 +1,6 @@
 Things to do:
 =============
 
-- String: Boundary checking on index and subtring operators
 - String: test cases for numerical conversion
 - String: Implement String != regex operator
 - String: index and rindex methods with String argument
index 8c154be..02cafc4 100644 (file)
@@ -381,4 +381,21 @@ public:
    friend bool operator == (const regex &r, const String &s);
 };
 
+class StringException
+{
+   String message;
+
+public:
+
+   StringException(String m)
+   {
+      message = m;
+   }
+
+   String what()
+   {
+      return message;
+   }
+};
+
 #endif  /* STRING_H */
index 8644e66..742fa1b 100644 (file)
@@ -351,12 +351,15 @@ String & String::operator>>=(int n)
 
 /*  Substring selection and assignment */
 
-// TODO: Boundary check
-
 substring String::operator()(int start, int len)
 {
    substring sub;
 
+   if (start >= strlen(p->s) || start + len >= strlen(p->s))
+   {
+      throw StringException("Substring Out of bounds: (" 
+                    + String(start) + ", " + String(len) + ")");
+   }
    sub.str = this;
    sub.start = start;
    sub.len   = len;
@@ -431,6 +434,11 @@ std::istream& operator>>(std::istream& s, String& x)
 
 char& String::operator[](int i)
 {
+   if (i >= strlen(p->s))
+   {
+      throw StringException("Out of bounds: " + String(i));
+   }
+
    return p->s[i];
 }
 
index 9b2d6cd..e824c6d 100644 (file)
@@ -72,17 +72,31 @@ int main()
    assert(c == 'd');
 
    // Out of bounds
-   //c = s1[-1];
-   //std::cout << "Seventh character of " << s1 << " char(" << (int)c << ")\n";
+   try
+   {
+      c = s1[-1];
+      std::cout << "Seventh character of " << s1 << " char(" << (int)c << ")\n";
+   }
+   catch (StringException se)
+   {
+      std::cout << "String exception: " << se.what() << "\n";
+   }
    //assert(c == 'a');
 
    s1[2] = 'Z';
    std::cout << "After \"abcde\"[2] = 'Z' : " << s1 << "\n";
    assert(s1 == "abZde");
 
-   s1[5] = 'X';
+   try
+   {
+      s1[5] = 'X';
+   }
+   catch (StringException se)
+   {
+      std::cout << "String exception: " << se.what() << "\n";
+   }
    std::cout << "After \"abcde\"[5] = 'X' : " << s1 << "\n";
-   //assert(s1 == "abZde");
+   assert(s1 == "abZde");
 
    return 0;
 }
index 8b99b10..cc4d34a 100644 (file)
@@ -6,6 +6,8 @@ The default contructor makes an empty string: ""
 The length of "abcde" is 5
 First character of abcde 'a'
 Fourth character of abcde 'd'
+String exception: Out of bounds: -1
 After "abcde"[2] = 'Z' : abZde
+String exception: Out of bounds: 5
 After "abcde"[5] = 'X' : abZde
 PASS string_basics (exit status: 0)
index ec2df92..a6119b7 100644 (file)
@@ -42,6 +42,21 @@ int main()
    std::cout << s5 << "\n";
    assert(s5 == "abc12345678ijkl");
 
+   // Select a substring out of bounds
+   try
+   {
+      String s7 = "abcdefghijkl";
+      String s8 = s7(9,5);         // s7 = "jkl.."
+
+      std::cout << "The substring (9,5) of " << s7 << " is " << s8 << "\n";
+   }
+   catch (StringException se)
+   {
+      std::cout << "String exception: " << se.what() << "\n";
+   }
+
+   //assert(s2 == "defgh");
+
    return 0;
 }
 
index 734353e..2fe771e 100644 (file)
@@ -2,4 +2,5 @@ The substring (3,5) of abcdefghijkl is defgh
 Replace substring (3,5) of abcdefghijkl with 12345678 : abc12345678ijkl
 Insert "12345678" into "abcdefghijkl" : abc12345678defghijkl
 Remove part of "abc12345678defghijkl" : abc12345678ijkl
+String exception: Substring Out of bounds: (9, 5)
 PASS string_substring (exit status: 0)