From 5b222135f8d2492713994f2cb003980e87ce6a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 10 Jun 2007 09:51:05 +0000 Subject: Make identifiers str (not str8) objects throughout. This affects the parser, various object implementations, and all places that put identifiers into C string literals. In testing, a number of crashes occurred as code would fail when the recursion limit was reached (such as the Unicode interning dictionary having key/value pairs where key is not value). To solve these, I added an overflowed flag, which allows for 50 more recursions after the limit was reached and the exception was raised, and a recursion_critical flag, which indicates that recursion absolutely must be allowed, i.e. that a certain call must not cause a stack overflow exception. There are still some places where both str and str8 are accepted as identifiers; these should eventually be removed. --- Include/ceval.h | 13 ++++++++++++- Include/pystate.h | 4 ++++ Include/stringobject.h | 4 ++-- Include/unicodeobject.h | 36 ++++++++++++++++++++++++++++++++---- 4 files changed, 50 insertions(+), 7 deletions(-) (limited to 'Include') diff --git a/Include/ceval.h b/Include/ceval.h index 15b29c6615..c9c59eb17c 100644 --- a/Include/ceval.h +++ b/Include/ceval.h @@ -50,7 +50,10 @@ PyAPI_FUNC(int) Py_GetRecursionLimit(void); (_Py_MakeRecCheck(PyThreadState_GET()->recursion_depth) && \ _Py_CheckRecursiveCall(where)) #define Py_LeaveRecursiveCall() \ - (--PyThreadState_GET()->recursion_depth) + do{ if((--PyThreadState_GET()->recursion_depth) < \ + _Py_CheckRecursionLimit - 50); \ + PyThreadState_GET()->overflowed = 0; \ + } while(0) PyAPI_FUNC(int) _Py_CheckRecursiveCall(char *where); PyAPI_DATA(int) _Py_CheckRecursionLimit; #ifdef USE_STACKCHECK @@ -59,6 +62,14 @@ PyAPI_DATA(int) _Py_CheckRecursionLimit; # define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit) #endif +#define Py_ALLOW_RECURSION \ + do { unsigned char _old = PyThreadState_GET()->recursion_critical;\ + PyThreadState_GET()->recursion_critical = 1; + +#define Py_END_ALLOW_RECURSION \ + PyThreadState_GET()->recursion_critical = _old; \ + } while(0); + PyAPI_FUNC(const char *) PyEval_GetFuncName(PyObject *); PyAPI_FUNC(const char *) PyEval_GetFuncDesc(PyObject *); diff --git a/Include/pystate.h b/Include/pystate.h index 4919d99b6c..0681e6565e 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -61,6 +61,10 @@ typedef struct _ts { struct _frame *frame; int recursion_depth; + char overflowed; /* The stack has overflowed. Allow 50 more calls + to handle the runtime error. */ + char recursion_critical; /* The current calls must not cause + a stack overflow. */ /* 'tracing' keeps track of the execution depth when tracing/profiling. This is to prevent the actual trace/profile code from being recorded in the trace/profile. */ diff --git a/Include/stringobject.h b/Include/stringobject.h index 2b8cc2fdef..0a932f043a 100644 --- a/Include/stringobject.h +++ b/Include/stringobject.h @@ -84,8 +84,8 @@ PyAPI_FUNC(void) _Py_ReleaseInternedStrings(void); #define PyString_CHECK_INTERNED(op) (((PyStringObject *)(op))->ob_sstate) /* Macro, trading safety for speed */ -#define PyString_AS_STRING(op) (((PyStringObject *)(op))->ob_sval) -#define PyString_GET_SIZE(op) (((PyStringObject *)(op))->ob_size) +#define PyString_AS_STRING(op) (assert(PyString_Check(op)),(((PyStringObject *)(op))->ob_sval)) +#define PyString_GET_SIZE(op) (assert(PyString_Check(op)),(((PyStringObject *)(op))->ob_size)) /* _PyString_Join(sep, x) is like sep.join(x). sep must be PyStringObject*, x must be an iterable object. */ diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index 2a27dbc0c8..1f6b729b40 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -410,13 +410,13 @@ PyAPI_DATA(PyTypeObject) PyUnicode_Type; /* Fast access macros */ #define PyUnicode_GET_SIZE(op) \ - (((PyUnicodeObject *)(op))->length) + (assert(PyUnicode_Check(op)),(((PyUnicodeObject *)(op))->length)) #define PyUnicode_GET_DATA_SIZE(op) \ - (((PyUnicodeObject *)(op))->length * sizeof(Py_UNICODE)) + (assert(PyUnicode_Check(op)),(((PyUnicodeObject *)(op))->length * sizeof(Py_UNICODE))) #define PyUnicode_AS_UNICODE(op) \ - (((PyUnicodeObject *)(op))->str) + (assert(PyUnicode_Check(op)),(((PyUnicodeObject *)(op))->str)) #define PyUnicode_AS_DATA(op) \ - ((const char *)((PyUnicodeObject *)(op))->str) + (assert(PyUnicode_Check(op)),((const char *)((PyUnicodeObject *)(op))->str)) /* --- Constants ---------------------------------------------------------- */ @@ -627,6 +627,13 @@ PyAPI_FUNC(PyObject*) PyUnicode_FromOrdinal(int ordinal); PyAPI_FUNC(PyObject *) _PyUnicode_AsDefaultEncodedString( PyObject *, const char *); +/* Return a char* holding the default encoded value of the + Unicode object. +*/ + +PyAPI_FUNC(char *) PyUnicode_AsString(PyObject*); + + /* Returns the currently active default encoding. The default encoding is currently implemented as run-time settable @@ -1193,6 +1200,11 @@ PyAPI_FUNC(int) PyUnicode_Compare( PyObject *right /* Right string */ ); +PyAPI_FUNC(int) PyUnicode_CompareWithASCIIString( + PyObject *left, + const char *right + ); + /* Rich compare two strings and return one of the following: - NULL in case an exception was raised @@ -1310,6 +1322,22 @@ PyAPI_FUNC(int) _PyUnicode_IsAlpha( Py_UNICODE ch /* Unicode character */ ); +PyAPI_FUNC(size_t) Py_UNICODE_strlen(const Py_UNICODE *u); + +PyAPI_FUNC(Py_UNICODE*) Py_UNICODE_strcpy( + Py_UNICODE *s1, const Py_UNICODE *s2); + +PyAPI_FUNC(Py_UNICODE*) Py_UNICODE_strncpy( + Py_UNICODE *s1, const Py_UNICODE *s2, size_t n); + +PyAPI_FUNC(int) Py_UNICODE_strcmp( + const Py_UNICODE *s1, const Py_UNICODE *s2); + +PyAPI_FUNC(Py_UNICODE*) Py_UNICODE_strchr( + const Py_UNICODE *s, Py_UNICODE c + ); + + #ifdef __cplusplus } #endif -- cgit v1.2.1