Added checks to prevent PyUnicode_Count() from dumping core
in case the parameters are out of bounds and fixes error handling
for .count(), .startswith() and .endswith() for the case of
mixed string/Unicode objects.

This patch adds Python style index semantics to PyUnicode_Count()
indices (including the special handling of negative indices).

The patch is an extended version of patch #103249 submitted
by Michael Hudson (mwh) on SF. It also includes new test cases.
diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py
index d4041be..067ccca 100644
--- a/Lib/test/string_tests.py
+++ b/Lib/test/string_tests.py
@@ -53,6 +53,10 @@
 
     test('capitalize', ' hello ', ' hello ')
     test('capitalize', 'hello ', 'Hello ')
+
+    test('count', 'aaa', 3, 'a')
+    test('count', 'aaa', 0, 'b')
+    
     test('find', 'abcdefghiabc', 0, 'abc')
     test('find', 'abcdefghiabc', 9, 'abc', 1)
     test('find', 'abcdefghiabc', -1, 'def', 4)
diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py
index 579bab1..c71f927 100644
--- a/Lib/test/test_unicode.py
+++ b/Lib/test/test_unicode.py
@@ -32,6 +32,13 @@
 test('capitalize', u' hello ', u' hello ')
 test('capitalize', u'hello ', u'Hello ')
 
+test('count', u'aaa', 3, u'a')
+test('count', u'aaa', 0, u'b')
+test('count', 'aaa', 3, u'a')
+test('count', 'aaa', 0, u'b')
+test('count', u'aaa', 3, 'a')
+test('count', u'aaa', 0, 'b')
+
 test('title', u' hello ', u' Hello ')
 test('title', u'hello ', u'Hello ')
 test('title', u"fOrMaT thIs aS titLe String", u'Format This As Title String')
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 091ede7..eed4687 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -1236,9 +1236,14 @@
 		sub = PyString_AS_STRING(subobj);
 		n = PyString_GET_SIZE(subobj);
 	}
-	else if (PyUnicode_Check(subobj))
-		return PyInt_FromLong(
-		        PyUnicode_Count((PyObject *)self, subobj, i, last));
+	else if (PyUnicode_Check(subobj)) {
+		int count;
+		count = PyUnicode_Count((PyObject *)self, subobj, i, last);
+		if (count == -1)
+			return NULL;
+		else
+		    	return PyInt_FromLong((long) count);
+	}
 	else if (PyObject_AsCharBuffer(subobj, &sub, &n))
 		return NULL;
 
@@ -1637,10 +1642,15 @@
 		prefix = PyString_AS_STRING(subobj);
 		plen = PyString_GET_SIZE(subobj);
 	}
-	else if (PyUnicode_Check(subobj))
-		return PyInt_FromLong(
-		        PyUnicode_Tailmatch((PyObject *)self, 
-					    subobj, start, end, -1));
+	else if (PyUnicode_Check(subobj)) {
+	    	int rc;
+		rc = PyUnicode_Tailmatch((PyObject *)self, 
+					  subobj, start, end, -1);
+		if (rc == -1)
+			return NULL;
+		else
+			return PyInt_FromLong((long) rc);
+	}
 	else if (PyObject_AsCharBuffer(subobj, &prefix, &plen))
 		return NULL;
 
@@ -1690,10 +1700,15 @@
 		suffix = PyString_AS_STRING(subobj);
 		slen = PyString_GET_SIZE(subobj);
 	}
-	else if (PyUnicode_Check(subobj))
-		return PyInt_FromLong(
-		        PyUnicode_Tailmatch((PyObject *)self, 
-					    subobj, start, end, +1));
+	else if (PyUnicode_Check(subobj)) {
+	    	int rc;
+		rc = PyUnicode_Tailmatch((PyObject *)self, 
+					  subobj, start, end, +1);
+		if (rc == -1)
+			return NULL;
+		else
+			return PyInt_FromLong((long) rc);
+	}
 	else if (PyObject_AsCharBuffer(subobj, &suffix, &slen))
 		return NULL;
 
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 8f7b354..a3678d5 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -1976,7 +1976,7 @@
 		x = Py_None;
 		Py_INCREF(x);
 	    } else
-	    goto onError;
+		goto onError;
 	}
 
 	/* Apply mapping */
@@ -2014,9 +2014,9 @@
 			         (targetsize << 2);
 		    extrachars += needed;
 		    if (_PyUnicode_Resize(v, PyUnicode_GET_SIZE(v) + needed)) {
-		Py_DECREF(x);
-		goto onError;
-	    }
+			Py_DECREF(x);
+			goto onError;
+		    }
 		    p = PyUnicode_AS_UNICODE(v) + oldpos;
 		}
 		Py_UNICODE_COPY(p,
@@ -2112,7 +2112,7 @@
 		x = Py_None;
 		Py_INCREF(x);
 	    } else
-	    goto onError;
+		goto onError;
 	}
 
 	/* Apply mapping */
@@ -2150,9 +2150,9 @@
 			         (targetsize << 2);
 		    extrachars += needed;
 		    if (_PyString_Resize(&v, PyString_GET_SIZE(v) + needed)) {
-		Py_DECREF(x);
-		goto onError;
-	    }
+			Py_DECREF(x);
+			goto onError;
+		    }
 		    s = PyString_AS_STRING(v) + oldpos;
 		}
 		memcpy(s,
@@ -2392,6 +2392,17 @@
 {
     int count = 0;
 
+    if (start < 0)
+        start += self->length;
+    if (start < 0)
+        start = 0;
+    if (end > self->length)
+        end = self->length;
+    if (end < 0)
+        end += self->length;
+    if (end < 0)
+        end = 0;
+
     if (substring->length == 0)
 	return (end - start + 1);