Python-2.7.3/Parser/myreadline.c

Location Tool Test ID Function Issue
/builddir/build/BUILD/Python-2.7.3/Parser/myreadline.c:149:20 clang-analyzer Potential leak of memory pointed to by 'p'
  1 /* Readline interface for tokenizer.c and [raw_]input() in bltinmodule.c.
  2    By default, or when stdin is not a tty device, we have a super
  3    simple my_readline function using fgets.
  4    Optionally, we can use the GNU readline library.
  5    my_readline() has a different return value from GNU readline():
  6    - NULL if an interrupt occurred or if an error occurred
  7    - a malloc'ed empty string if EOF was read
  8    - a malloc'ed string ending in \n normally
  9 */
 10 
 11 #include "Python.h"
 12 #ifdef MS_WINDOWS
 13 #define WIN32_LEAN_AND_MEAN
 14 #include "windows.h"
 15 #endif /* MS_WINDOWS */
 16 
 17 #ifdef __VMS
 18 extern char* vms__StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt);
 19 #endif
 20 
 21 
 22 PyThreadState* _PyOS_ReadlineTState;
 23 
 24 #ifdef WITH_THREAD
 25 #include "pythread.h"
 26 static PyThread_type_lock _PyOS_ReadlineLock = NULL;
 27 #endif
 28 
 29 int (*PyOS_InputHook)(void) = NULL;
 30 
 31 #ifdef RISCOS
 32 int Py_RISCOSWimpFlag;
 33 #endif
 34 
 35 /* This function restarts a fgets() after an EINTR error occurred
 36    except if PyOS_InterruptOccurred() returns true. */
 37 
 38 static int
 39 my_fgets(char *buf, int len, FILE *fp)
 40 {
 41     char *p;
 42     while (1) {
 43         if (PyOS_InputHook != NULL)
 44             (void)(PyOS_InputHook)();
 45         errno = 0;
 46         clearerr(fp);
 47         p = fgets(buf, len, fp);
 48         if (p != NULL)
 49             return 0; /* No error */
 50 #ifdef MS_WINDOWS
 51         /* In the case of a Ctrl+C or some other external event
 52            interrupting the operation:
 53            Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32
 54            error code (and feof() returns TRUE).
 55            Win9x: Ctrl+C seems to have no effect on fgets() returning
 56            early - the signal handler is called, but the fgets()
 57            only returns "normally" (ie, when Enter hit or feof())
 58         */
 59         if (GetLastError()==ERROR_OPERATION_ABORTED) {
 60             /* Signals come asynchronously, so we sleep a brief
 61                moment before checking if the handler has been
 62                triggered (we cant just return 1 before the
 63                signal handler has been called, as the later
 64                signal may be treated as a separate interrupt).
 65             */
 66             Sleep(1);
 67             if (PyOS_InterruptOccurred()) {
 68                 return 1; /* Interrupt */
 69             }
 70             /* Either the sleep wasn't long enough (need a
 71                short loop retrying?) or not interrupted at all
 72                (in which case we should revisit the whole thing!)
 73                Logging some warning would be nice.  assert is not
 74                viable as under the debugger, the various dialogs
 75                mean the condition is not true.
 76             */
 77         }
 78 #endif /* MS_WINDOWS */
 79         if (feof(fp)) {
 80             clearerr(fp);
 81             return -1; /* EOF */
 82         }
 83 #ifdef EINTR
 84         if (errno == EINTR) {
 85             int s;
 86 #ifdef WITH_THREAD
 87             PyEval_RestoreThread(_PyOS_ReadlineTState);
 88 #endif
 89             s = PyErr_CheckSignals();
 90 #ifdef WITH_THREAD
 91             PyEval_SaveThread();
 92 #endif
 93             if (s < 0)
 94                     return 1;
 95 	    /* try again */
 96             continue;
 97         }
 98 #endif
 99         if (PyOS_InterruptOccurred()) {
100             return 1; /* Interrupt */
101         }
102         return -2; /* Error */
103     }
104     /* NOTREACHED */
105 }
106 
107 
108 /* Readline implementation using fgets() */
109 
110 char *
111 PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
112 {
113     size_t n;
114     char *p;
115     n = 100;
116     if ((p = (char *)PyMem_MALLOC(n)) == NULL)
117         return NULL;
118     fflush(sys_stdout);
119 #ifndef RISCOS
120     if (prompt)
121         fprintf(stderr, "%s", prompt);
122 #else
123     if (prompt) {
124         if(Py_RISCOSWimpFlag)
125             fprintf(stderr, "\x0cr%s\x0c", prompt);
126         else
127             fprintf(stderr, "%s", prompt);
128     }
129 #endif
130     fflush(stderr);
131     switch (my_fgets(p, (int)n, sys_stdin)) {
132     case 0: /* Normal case */
133         break;
134     case 1: /* Interrupt */
135         PyMem_FREE(p);
136         return NULL;
137     case -1: /* EOF */
138     case -2: /* Error */
139     default: /* Shouldn't happen */
140         *p = '\0';
141         break;
142     }
143     n = strlen(p);
144     while (n > 0 && p[n-1] != '\n') {
145         size_t incr = n+2;
146         p = (char *)PyMem_REALLOC(p, n + incr);
147         if (p == NULL)
148             return NULL;
149         if (incr > INT_MAX) {
Potential leak of memory pointed to by 'p'
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

150 PyErr_SetString(PyExc_OverflowError, "input line too long"); 151 } 152 if (my_fgets(p+n, (int)incr, sys_stdin) != 0) 153 break; 154 n += strlen(p+n); 155 } 156 return (char *)PyMem_REALLOC(p, n+1); 157 } 158 159 160 /* By initializing this function pointer, systems embedding Python can 161 override the readline function. 162 163 Note: Python expects in return a buffer allocated with PyMem_Malloc. */ 164 165 char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, char *); 166 167 168 /* Interface used by tokenizer.c and bltinmodule.c */ 169 170 char * 171 PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt) 172 { 173 char *rv; 174 175 if (_PyOS_ReadlineTState == PyThreadState_GET()) { 176 PyErr_SetString(PyExc_RuntimeError, 177 "can't re-enter readline"); 178 return NULL; 179 } 180 181 182 if (PyOS_ReadlineFunctionPointer == NULL) { 183 #ifdef __VMS 184 PyOS_ReadlineFunctionPointer = vms__StdioReadline; 185 #else 186 PyOS_ReadlineFunctionPointer = PyOS_StdioReadline; 187 #endif 188 } 189 190 #ifdef WITH_THREAD 191 if (_PyOS_ReadlineLock == NULL) { 192 _PyOS_ReadlineLock = PyThread_allocate_lock(); 193 } 194 #endif 195 196 _PyOS_ReadlineTState = PyThreadState_GET(); 197 Py_BEGIN_ALLOW_THREADS 198 #ifdef WITH_THREAD 199 PyThread_acquire_lock(_PyOS_ReadlineLock, 1); 200 #endif 201 202 /* This is needed to handle the unlikely case that the 203 * interpreter is in interactive mode *and* stdin/out are not 204 * a tty. This can happen, for example if python is run like 205 * this: python -i < test1.py 206 */ 207 if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout))) 208 rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt); 209 else 210 rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout, 211 prompt); 212 Py_END_ALLOW_THREADS 213 214 #ifdef WITH_THREAD 215 PyThread_release_lock(_PyOS_ReadlineLock); 216 #endif 217 218 _PyOS_ReadlineTState = NULL; 219 220 return rv; 221 }