wchar_t* _Py_wgetcwd(wchar_t *buf, size_t size) { #ifdef MS_WINDOWS int isize = (int)Py_MIN(size, INT_MAX); return _wgetcwd(buf, isize); #else char fname[MAXPATHLEN]; wchar_t *wname; size_t len; if (getcwd(fname, Py_ARRAY_LENGTH(fname)) == NULL) return NULL; wname = _Py_char2wchar(fname, &len); if (wname == NULL) return NULL; if (size <= len) { PyMem_RawFree(wname); return NULL; } wcsncpy(buf, wname, size); PyMem_RawFree(wname); return buf; #endif }
/* Call getrandom() to get random bytes: - Return 1 on success - Return 0 if getrandom() is not available (failed with ENOSYS or EPERM), or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not initialized yet) and raise=0. - Raise an exception (if raise is non-zero) and return -1 on error: if getrandom() failed with EINTR, raise is non-zero and the Python signal handler raised an exception, or if getrandom() failed with a different error. getrandom() is retried if it failed with EINTR: interrupted by a signal. */ static int py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise) { /* Is getrandom() supported by the running kernel? Set to 0 if getrandom() failed with ENOSYS or EPERM. Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */ static int getrandom_works = 1; int flags; char *dest; long n; if (!getrandom_works) { return 0; } flags = blocking ? 0 : GRND_NONBLOCK; dest = buffer; while (0 < size) { #ifdef sun /* Issue #26735: On Solaris, getrandom() is limited to returning up to 1024 bytes. Call it multiple times if more bytes are requested. */ n = Py_MIN(size, 1024); #else n = Py_MIN(size, LONG_MAX); #endif errno = 0; #ifdef HAVE_GETRANDOM if (raise) { Py_BEGIN_ALLOW_THREADS n = getrandom(dest, n, flags); Py_END_ALLOW_THREADS } else { n = getrandom(dest, n, flags); } #else /* On Linux, use the syscall() function because the GNU libc doesn't expose the Linux getrandom() syscall yet. See: https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */ if (raise) { Py_BEGIN_ALLOW_THREADS n = syscall(SYS_getrandom, dest, n, flags); Py_END_ALLOW_THREADS } else {
/* Fill buffer with size pseudo-random bytes generated by getentropy(). Return 0 on success, or raise an exception and return -1 on error. If fatal is nonzero, call Py_FatalError() instead of raising an exception on error. */ static int py_getentropy(unsigned char *buffer, Py_ssize_t size, int fatal) { while (size > 0) { Py_ssize_t len = Py_MIN(size, 256); int res; if (!fatal) { Py_BEGIN_ALLOW_THREADS res = getentropy(buffer, len); Py_END_ALLOW_THREADS if (res < 0) { PyErr_SetFromErrno(PyExc_OSError); return -1; } } else {
static PyObject * Billiard_send(PyObject *self, PyObject *args) { HANDLE handle; Py_buffer buf; int ret, length; if (!PyArg_ParseTuple(args, F_HANDLE "y*:send" , &handle, &buf)) return NULL; length = (int)Py_MIN(buf.len, INT_MAX); Py_BEGIN_ALLOW_THREADS ret = send((SOCKET) handle, buf.buf, length, 0); Py_END_ALLOW_THREADS PyBuffer_Release(&buf); if (ret < 0) return PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError()); return PyLong_FromLong(ret); }
static PyObject * oss_writeall(oss_audio_t *self, PyObject *args) { Py_buffer data; const char *cp; Py_ssize_t size; Py_ssize_t rv; fd_set write_set_fds; int select_rv; /* NB. writeall() is only useful in non-blocking mode: according to Guenter Geiger <*****@*****.**> on the linux-audio-dev list (http://eca.cx/lad/2002/11/0380.html), OSS guarantees that write() in blocking mode consumes the whole buffer. In blocking mode, the behaviour of write() and writeall() from Python is indistinguishable. */ if (!_is_fd_valid(self->fd)) return NULL; if (!PyArg_ParseTuple(args, "y*:writeall", &data)) return NULL; if (!_PyIsSelectable_fd(self->fd)) { PyErr_SetString(PyExc_ValueError, "file descriptor out of range for select"); PyBuffer_Release(&data); return NULL; } /* use select to wait for audio device to be available */ FD_ZERO(&write_set_fds); FD_SET(self->fd, &write_set_fds); cp = (const char *)data.buf; size = data.len; while (size > 0) { Py_BEGIN_ALLOW_THREADS select_rv = select(self->fd+1, NULL, &write_set_fds, NULL, NULL); Py_END_ALLOW_THREADS assert(select_rv != 0); /* no timeout, can't expire */ if (select_rv == -1) { PyBuffer_Release(&data); return PyErr_SetFromErrno(PyExc_OSError); } rv = _Py_write(self->fd, cp, Py_MIN(size, INT_MAX)); if (rv == -1) { /* buffer is full, try again */ if (errno == EAGAIN) { PyErr_Clear(); continue; } /* it's a real error */ PyBuffer_Release(&data); return NULL; } /* wrote rv bytes */ self->ocount += rv; size -= rv; cp += rv; } PyBuffer_Release(&data); Py_RETURN_NONE; }
int main(int argc, char *argv[]) { char *inpath, *outpath; FILE *infile, *outfile = NULL; struct stat st; size_t text_size, data_size, n; char *text; unsigned char *data; PyObject *code, *marshalled; if (argc != 3) { fprintf(stderr, "need to specify input and output paths\n"); return 2; } inpath = argv[1]; outpath = argv[2]; infile = fopen(inpath, "rb"); if (infile == NULL) { fprintf(stderr, "cannot open '%s' for reading\n", inpath); return 1; } if (fstat(fileno(infile), &st)) { fclose(infile); fprintf(stderr, "cannot fstat '%s'\n", inpath); return 1; } text_size = st.st_size; text = (char *) malloc(text_size + 1); if (text == NULL) { fclose(infile); fprintf(stderr, "could not allocate %ld bytes\n", (long) text_size); return 1; } n = fread(text, 1, text_size, infile); fclose(infile); infile = NULL; if (n < text_size) { fprintf(stderr, "read too short: got %ld instead of %ld bytes\n", (long) n, (long) text_size); return 1; } text[text_size] = '\0'; Py_NoUserSiteDirectory++; Py_NoSiteFlag++; Py_IgnoreEnvironmentFlag++; Py_SetProgramName(L"./_freeze_importlib"); /* Don't install importlib, since it could execute outdated bytecode. */ _Py_InitializeEx_Private(1, 0); code = Py_CompileStringExFlags(text, "<frozen importlib._bootstrap>", Py_file_input, NULL, 0); if (code == NULL) goto error; marshalled = PyMarshal_WriteObjectToString(code, Py_MARSHAL_VERSION); Py_DECREF(code); if (marshalled == NULL) goto error; assert(PyBytes_CheckExact(marshalled)); data = (unsigned char *) PyBytes_AS_STRING(marshalled); data_size = PyBytes_GET_SIZE(marshalled); outfile = fopen(outpath, "wb"); if (outfile == NULL) { fprintf(stderr, "cannot open '%s' for writing\n", outpath); return 1; } fprintf(outfile, "%s\n", header); fprintf(outfile, "unsigned char _Py_M__importlib[] = {\n"); for (n = 0; n < data_size; n += 16) { size_t i, end = Py_MIN(n + 16, data_size); fprintf(outfile, " "); for (i = n; i < end; i++) { fprintf(outfile, "%d,", (unsigned int) data[i]); } fprintf(outfile, "\n"); } fprintf(outfile, "};\n"); Py_DECREF(marshalled); Py_Finalize(); if (infile) fclose(infile); if (outfile) { if (ferror(outfile)) { fprintf(stderr, "error when writing to '%s'\n", outpath); fclose(outfile); return 1; } fclose(outfile); } return 0; error: PyErr_Print(); Py_Finalize(); if (infile) fclose(infile); if (outfile) fclose(outfile); return 1; }
/* Setter for f_lineno - you can set f_lineno from within a trace function in * order to jump to a given line of code, subject to some restrictions. Most * lines are OK to jump to because they don't make any assumptions about the * state of the stack (obvious because you could remove the line and the code * would still work without any stack errors), but there are some constructs * that limit jumping: * * o Lines with an 'except' statement on them can't be jumped to, because * they expect an exception to be on the top of the stack. * o Lines that live in a 'finally' block can't be jumped from or to, since * the END_FINALLY expects to clean up the stack after the 'try' block. * o 'try'/'for'/'while' blocks can't be jumped into because the blockstack * needs to be set up before their code runs, and for 'for' loops the * iterator needs to be on the stack. */ static int frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno) { int new_lineno = 0; /* The new value of f_lineno */ long l_new_lineno; int overflow; int new_lasti = 0; /* The new value of f_lasti */ int new_iblock = 0; /* The new value of f_iblock */ unsigned char *code = NULL; /* The bytecode for the frame... */ Py_ssize_t code_len = 0; /* ...and its length */ unsigned char *lnotab = NULL; /* Iterating over co_lnotab */ Py_ssize_t lnotab_len = 0; /* (ditto) */ int offset = 0; /* (ditto) */ int line = 0; /* (ditto) */ int addr = 0; /* (ditto) */ int min_addr = 0; /* Scanning the SETUPs and POPs */ int max_addr = 0; /* (ditto) */ int delta_iblock = 0; /* (ditto) */ int min_delta_iblock = 0; /* (ditto) */ int min_iblock = 0; /* (ditto) */ int f_lasti_setup_addr = 0; /* Policing no-jump-into-finally */ int new_lasti_setup_addr = 0; /* (ditto) */ int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */ int in_finally[CO_MAXBLOCKS]; /* (ditto) */ int blockstack_top = 0; /* (ditto) */ unsigned char setup_op = 0; /* (ditto) */ /* f_lineno must be an integer. */ if (!PyLong_CheckExact(p_new_lineno)) { PyErr_SetString(PyExc_ValueError, "lineno must be an integer"); return -1; } /* You can only do this from within a trace function, not via * _getframe or similar hackery. */ if (!f->f_trace) { PyErr_Format(PyExc_ValueError, "f_lineno can only be set by a" " line trace function"); return -1; } /* Fail if the line comes before the start of the code block. */ l_new_lineno = PyLong_AsLongAndOverflow(p_new_lineno, &overflow); if (overflow #if SIZEOF_LONG > SIZEOF_INT || l_new_lineno > INT_MAX || l_new_lineno < INT_MIN #endif ) { PyErr_SetString(PyExc_ValueError, "lineno out of range"); return -1; } new_lineno = (int)l_new_lineno; if (new_lineno < f->f_code->co_firstlineno) { PyErr_Format(PyExc_ValueError, "line %d comes before the current code block", new_lineno); return -1; } else if (new_lineno == f->f_code->co_firstlineno) { new_lasti = 0; new_lineno = f->f_code->co_firstlineno; } else { /* Find the bytecode offset for the start of the given * line, or the first code-owning line after it. */ char *tmp; PyBytes_AsStringAndSize(f->f_code->co_lnotab, &tmp, &lnotab_len); lnotab = (unsigned char *) tmp; addr = 0; line = f->f_code->co_firstlineno; new_lasti = -1; for (offset = 0; offset < lnotab_len; offset += 2) { addr += lnotab[offset]; line += lnotab[offset+1]; if (line >= new_lineno) { new_lasti = addr; new_lineno = line; break; } } } /* If we didn't reach the requested line, return an error. */ if (new_lasti == -1) { PyErr_Format(PyExc_ValueError, "line %d comes after the current code block", new_lineno); return -1; } /* We're now ready to look at the bytecode. */ PyBytes_AsStringAndSize(f->f_code->co_code, (char **)&code, &code_len); min_addr = Py_MIN(new_lasti, f->f_lasti); max_addr = Py_MAX(new_lasti, f->f_lasti); /* You can't jump onto a line with an 'except' statement on it - * they expect to have an exception on the top of the stack, which * won't be true if you jump to them. They always start with code * that either pops the exception using POP_TOP (plain 'except:' * lines do this) or duplicates the exception on the stack using * DUP_TOP (if there's an exception type specified). See compile.c, * 'com_try_except' for the full details. There aren't any other * cases (AFAIK) where a line's code can start with DUP_TOP or * POP_TOP, but if any ever appear, they'll be subject to the same * restriction (but with a different error message). */ if (code[new_lasti] == DUP_TOP || code[new_lasti] == POP_TOP) { PyErr_SetString(PyExc_ValueError, "can't jump to 'except' line as there's no exception"); return -1; } /* You can't jump into or out of a 'finally' block because the 'try' * block leaves something on the stack for the END_FINALLY to clean * up. So we walk the bytecode, maintaining a simulated blockstack. * When we reach the old or new address and it's in a 'finally' block * we note the address of the corresponding SETUP_FINALLY. The jump * is only legal if neither address is in a 'finally' block or * they're both in the same one. 'blockstack' is a stack of the * bytecode addresses of the SETUP_X opcodes, and 'in_finally' tracks * whether we're in a 'finally' block at each blockstack level. */ f_lasti_setup_addr = -1; new_lasti_setup_addr = -1; memset(blockstack, '\0', sizeof(blockstack)); memset(in_finally, '\0', sizeof(in_finally)); blockstack_top = 0; for (addr = 0; addr < code_len; addr++) { unsigned char op = code[addr]; switch (op) { case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_WITH: blockstack[blockstack_top++] = addr; in_finally[blockstack_top-1] = 0; break; case POP_BLOCK: assert(blockstack_top > 0); setup_op = code[blockstack[blockstack_top-1]]; if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { in_finally[blockstack_top-1] = 1; } else { blockstack_top--; } break; case END_FINALLY: /* Ignore END_FINALLYs for SETUP_EXCEPTs - they exist * in the bytecode but don't correspond to an actual * 'finally' block. (If blockstack_top is 0, we must * be seeing such an END_FINALLY.) */ if (blockstack_top > 0) { setup_op = code[blockstack[blockstack_top-1]]; if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH) { blockstack_top--; } } break; } /* For the addresses we're interested in, see whether they're * within a 'finally' block and if so, remember the address * of the SETUP_FINALLY. */ if (addr == new_lasti || addr == f->f_lasti) { int i = 0; int setup_addr = -1; for (i = blockstack_top-1; i >= 0; i--) { if (in_finally[i]) { setup_addr = blockstack[i]; break; } } if (setup_addr != -1) { if (addr == new_lasti) { new_lasti_setup_addr = setup_addr; } if (addr == f->f_lasti) { f_lasti_setup_addr = setup_addr; } } } if (op >= HAVE_ARGUMENT) { addr += 2; } } /* Verify that the blockstack tracking code didn't get lost. */ assert(blockstack_top == 0); /* After all that, are we jumping into / out of a 'finally' block? */ if (new_lasti_setup_addr != f_lasti_setup_addr) { PyErr_SetString(PyExc_ValueError, "can't jump into or out of a 'finally' block"); return -1; } /* Police block-jumping (you can't jump into the middle of a block) * and ensure that the blockstack finishes up in a sensible state (by * popping any blocks we're jumping out of). We look at all the * blockstack operations between the current position and the new * one, and keep track of how many blocks we drop out of on the way. * By also keeping track of the lowest blockstack position we see, we * can tell whether the jump goes into any blocks without coming out * again - in that case we raise an exception below. */ delta_iblock = 0; for (addr = min_addr; addr < max_addr; addr++) { unsigned char op = code[addr]; switch (op) { case SETUP_LOOP: case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_WITH: delta_iblock++; break; case POP_BLOCK: delta_iblock--; break; } min_delta_iblock = Py_MIN(min_delta_iblock, delta_iblock); if (op >= HAVE_ARGUMENT) { addr += 2; } } /* Derive the absolute iblock values from the deltas. */ min_iblock = f->f_iblock + min_delta_iblock; if (new_lasti > f->f_lasti) { /* Forwards jump. */ new_iblock = f->f_iblock + delta_iblock; } else { /* Backwards jump. */ new_iblock = f->f_iblock - delta_iblock; } /* Are we jumping into a block? */ if (new_iblock > min_iblock) { PyErr_SetString(PyExc_ValueError, "can't jump into the middle of a block"); return -1; } /* Pop any blocks that we're jumping out of. */ while (f->f_iblock > new_iblock) { PyTryBlock *b = &f->f_blockstack[--f->f_iblock]; while ((f->f_stacktop - f->f_valuestack) > b->b_level) { PyObject *v = (*--f->f_stacktop); Py_DECREF(v); } } /* Finally set the new f_lineno and f_lasti and return OK. */ f->f_lineno = new_lineno; f->f_lasti = new_lasti; return 0; }