Ensure usage of __attribute__(cleanup) never frees un-initialized memory
Use macros that take an initializer parameter to, thereby ensuring the variable to be cleaned up is always initialized.
This commit is contained in:
parent
9af4d5e0fc
commit
6c7a8f8fa9
19 changed files with 75 additions and 77 deletions
|
|
@ -224,7 +224,7 @@ Patcher_dealloc(PyObject *self) {
|
|||
|
||||
static PyObject*
|
||||
signature_header(Patcher *self, PyObject *a2) {
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer dest = {0};
|
||||
RAII_PY_BUFFER(dest);
|
||||
if (PyObject_GetBuffer(a2, &dest, PyBUF_WRITE) == -1) return NULL;
|
||||
static const ssize_t header_size = 12;
|
||||
if (dest.len < header_size) {
|
||||
|
|
@ -243,8 +243,7 @@ static PyObject*
|
|||
sign_block(Patcher *self, PyObject *args) {
|
||||
PyObject *a1, *a2;
|
||||
if (!PyArg_ParseTuple(args, "OO", &a1, &a2)) return NULL;
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer src = {0};
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer dest = {0};
|
||||
RAII_PY_BUFFER(src); RAII_PY_BUFFER(dest);
|
||||
if (PyObject_GetBuffer(a1, &src, PyBUF_SIMPLE) == -1) return NULL;
|
||||
if (PyObject_GetBuffer(a2, &dest, PyBUF_WRITE) == -1) return NULL;
|
||||
if (dest.len < (ssize_t)signature_block_size) {
|
||||
|
|
@ -307,16 +306,16 @@ unserialize_op(uint8_t *data, size_t len, Operation *op) {
|
|||
|
||||
static bool
|
||||
write_block(Patcher *self, uint64_t block_index, PyObject *read, PyObject *write) {
|
||||
DECREF_AFTER_FUNCTION PyObject *pos = PyLong_FromUnsignedLongLong((unsigned long long)(self->rsync.block_size * block_index));
|
||||
RAII_PyObject(pos, PyLong_FromUnsignedLongLong((unsigned long long)(self->rsync.block_size * block_index)));
|
||||
if (!pos) return false;
|
||||
DECREF_AFTER_FUNCTION PyObject *ret = PyObject_CallFunctionObjArgs(read, pos, self->block_buf_view, NULL);
|
||||
RAII_PyObject(ret, PyObject_CallFunctionObjArgs(read, pos, self->block_buf_view, NULL));
|
||||
if (ret == NULL) return false;
|
||||
if (!PyLong_Check(ret)) { PyErr_SetString(PyExc_TypeError, "read callback function did not return an integer"); return false; }
|
||||
size_t n = PyLong_AsSize_t(ret);
|
||||
self->rsync.checksummer.update(self->rsync.checksummer.state, self->block_buf.data, n);
|
||||
DECREF_AFTER_FUNCTION PyObject *view = PyMemoryView_FromMemory((char*)self->block_buf.data, n, PyBUF_READ);
|
||||
RAII_PyObject(view, PyMemoryView_FromMemory((char*)self->block_buf.data, n, PyBUF_READ));
|
||||
if (!view) return false;
|
||||
DECREF_AFTER_FUNCTION PyObject *wret = PyObject_CallFunctionObjArgs(write, view, NULL);
|
||||
RAII_PyObject(wret, PyObject_CallFunctionObjArgs(write, view, NULL));
|
||||
if (wret == NULL) return false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -345,9 +344,9 @@ apply_op(Patcher *self, Operation op, PyObject *read, PyObject *write) {
|
|||
case OpData: {
|
||||
self->total_data_in_delta += op.data.len;
|
||||
self->rsync.checksummer.update(self->rsync.checksummer.state, op.data.buf, op.data.len);
|
||||
DECREF_AFTER_FUNCTION PyObject *view = PyMemoryView_FromMemory((char*)op.data.buf, op.data.len, PyBUF_READ);
|
||||
RAII_PyObject(view, PyMemoryView_FromMemory((char*)op.data.buf, op.data.len, PyBUF_READ));
|
||||
if (!view) return false;
|
||||
DECREF_AFTER_FUNCTION PyObject *wret = PyObject_CallFunctionObjArgs(write, view, NULL);
|
||||
RAII_PyObject(wret, PyObject_CallFunctionObjArgs(write, view, NULL));
|
||||
if (!wret) return false;
|
||||
} return true;
|
||||
case OpHash: {
|
||||
|
|
@ -357,9 +356,9 @@ apply_op(Patcher *self, Operation op, PyObject *read, PyObject *write) {
|
|||
if (memcmp(actual, op.data.buf, self->rsync.checksummer.hash_size) != 0) {
|
||||
char hexdigest[129];
|
||||
bytes_as_hex(actual, self->rsync.checksummer.hash_size, hexdigest);
|
||||
DECREF_AFTER_FUNCTION PyObject *h1 = PyUnicode_FromStringAndSize(hexdigest, 2*self->rsync.checksummer.hash_size);
|
||||
RAII_PyObject(h1, PyUnicode_FromStringAndSize(hexdigest, 2*self->rsync.checksummer.hash_size));
|
||||
bytes_as_hex(op.data.buf, op.data.len, hexdigest);
|
||||
DECREF_AFTER_FUNCTION PyObject *h2 = PyUnicode_FromStringAndSize(hexdigest, 2*self->rsync.checksummer.hash_size);
|
||||
RAII_PyObject(h2, PyUnicode_FromStringAndSize(hexdigest, 2*self->rsync.checksummer.hash_size));
|
||||
PyErr_Format(RsyncError, "Failed to verify overall file checksum actual: %S != expected: %S, this usually happens because one of the involved files was altered while the operation was in progress.", h1, h2);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -373,7 +372,7 @@ apply_op(Patcher *self, Operation op, PyObject *read, PyObject *write) {
|
|||
static PyObject*
|
||||
apply_delta_data(Patcher *self, PyObject *args) {
|
||||
PyObject *read, *write;
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer data = {0};
|
||||
RAII_PY_BUFFER(data);
|
||||
if (!PyArg_ParseTuple(args, "y*OO", &data, &read, &write)) return NULL;
|
||||
if (!write_to_buffer(&self->buf, data.buf, data.len)) return NULL;
|
||||
size_t pos = 0;
|
||||
|
|
@ -543,7 +542,7 @@ parse_signature_block(Differ *self, uint8_t *data, size_t len) {
|
|||
|
||||
static PyObject*
|
||||
add_signature_data(Differ *self, PyObject *args) {
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer data = {0};
|
||||
RAII_PY_BUFFER(data);
|
||||
if (!PyArg_ParseTuple(args, "y*", &data)) return NULL;
|
||||
if (!write_to_buffer(&self->buf, data.buf, data.len)) return NULL;
|
||||
if (!self->signature_header_parsed) {
|
||||
|
|
@ -597,12 +596,12 @@ send_op(Differ *self, Operation *op) {
|
|||
len = 5;
|
||||
break;
|
||||
}
|
||||
DECREF_AFTER_FUNCTION PyObject *mv = PyMemoryView_FromMemory((char*)metadata, len, PyBUF_READ);
|
||||
DECREF_AFTER_FUNCTION PyObject *ret = PyObject_CallFunctionObjArgs(self->write, mv, NULL);
|
||||
RAII_PyObject(mv, PyMemoryView_FromMemory((char*)metadata, len, PyBUF_READ));
|
||||
RAII_PyObject(ret, PyObject_CallFunctionObjArgs(self->write, mv, NULL));
|
||||
if (ret == NULL) return false;
|
||||
if (op->type == OpData) {
|
||||
DECREF_AFTER_FUNCTION PyObject *mv = PyMemoryView_FromMemory((char*)op->data.buf, op->data.len, PyBUF_READ);
|
||||
DECREF_AFTER_FUNCTION PyObject *ret = PyObject_CallFunctionObjArgs(self->write, mv, NULL);
|
||||
RAII_PyObject(mv, PyMemoryView_FromMemory((char*)op->data.buf, op->data.len, PyBUF_READ));
|
||||
RAII_PyObject(ret, PyObject_CallFunctionObjArgs(self->write, mv, NULL));
|
||||
if (ret == NULL) return false;
|
||||
}
|
||||
self->written = true;
|
||||
|
|
@ -648,9 +647,9 @@ ensure_idx_valid(Differ *self, size_t idx) {
|
|||
self->data.pos = 0;
|
||||
return ensure_idx_valid(self, distance_from_window_pos);
|
||||
}
|
||||
DECREF_AFTER_FUNCTION PyObject *mv = PyMemoryView_FromMemory((char*)self->buf.data + self->buf.len, self->buf.cap - self->buf.len, PyBUF_WRITE);
|
||||
RAII_PyObject(mv, PyMemoryView_FromMemory((char*)self->buf.data + self->buf.len, self->buf.cap - self->buf.len, PyBUF_WRITE));
|
||||
if (!mv) return false;
|
||||
DECREF_AFTER_FUNCTION PyObject *ret = PyObject_CallFunctionObjArgs(self->read, mv, NULL);
|
||||
RAII_PyObject(ret, PyObject_CallFunctionObjArgs(self->read, mv, NULL));
|
||||
if (!ret) return false;
|
||||
if (!PyLong_Check(ret)) { PyErr_SetString(PyExc_TypeError, "read callback did not return an integer"); return false; }
|
||||
size_t n = PyLong_AsSize_t(ret);
|
||||
|
|
@ -798,7 +797,7 @@ Hasher_init(PyObject *s, PyObject *args, PyObject *kwds) {
|
|||
Hasher *self = (Hasher*)s;
|
||||
static char *kwlist[] = {"which", "data", NULL};
|
||||
const char *which = "xxh3-64";
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer data = {0};
|
||||
RAII_PY_BUFFER(data);
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sy*", kwlist, &which, &data)) return -1;
|
||||
if (strcmp(which, "xxh3-64") == 0) {
|
||||
self->h = xxh64_hasher();
|
||||
|
|
@ -833,7 +832,7 @@ reset(Hasher *self, PyObject *args UNUSED) {
|
|||
|
||||
static PyObject*
|
||||
update(Hasher *self, PyObject *o) {
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer data = {0};
|
||||
RAII_PY_BUFFER(data);
|
||||
if (PyObject_GetBuffer(o, &data, PyBUF_SIMPLE) == -1) return NULL;
|
||||
if (data.buf && data.len > 0) {
|
||||
self->h.update(self->h.state, data.buf, data.len);
|
||||
|
|
@ -904,7 +903,7 @@ PyTypeObject Hasher_Type = {
|
|||
|
||||
static PyObject*
|
||||
decode_utf8_buffer(PyObject *self UNUSED, PyObject *args) {
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer buf = {0};
|
||||
RAII_PY_BUFFER(buf);
|
||||
if (!PyArg_ParseTuple(args, "s*", &buf)) return NULL;
|
||||
return PyUnicode_FromStringAndSize(buf.buf, buf.len);
|
||||
}
|
||||
|
|
@ -912,17 +911,17 @@ decode_utf8_buffer(PyObject *self UNUSED, PyObject *args) {
|
|||
static bool
|
||||
call_ftc_callback(PyObject *callback, char *src, Py_ssize_t key_start, Py_ssize_t key_length, Py_ssize_t val_start, Py_ssize_t val_length) {
|
||||
while(src[key_start] == ';' && key_length > 0 ) { key_start++; key_length--; }
|
||||
DECREF_AFTER_FUNCTION PyObject *k = PyMemoryView_FromMemory(src + key_start, key_length, PyBUF_READ);
|
||||
RAII_PyObject(k, PyMemoryView_FromMemory(src + key_start, key_length, PyBUF_READ));
|
||||
if (!k) return false;
|
||||
DECREF_AFTER_FUNCTION PyObject *v = PyMemoryView_FromMemory(src + val_start, val_length, PyBUF_READ);
|
||||
RAII_PyObject(v, PyMemoryView_FromMemory(src + val_start, val_length, PyBUF_READ));
|
||||
if (!v) return false;
|
||||
DECREF_AFTER_FUNCTION PyObject *ret = PyObject_CallFunctionObjArgs(callback, k, v, NULL);
|
||||
RAII_PyObject(ret, PyObject_CallFunctionObjArgs(callback, k, v, NULL));
|
||||
return ret != NULL;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
parse_ftc(PyObject *self UNUSED, PyObject *args) {
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer buf = {0};
|
||||
RAII_PY_BUFFER(buf);
|
||||
PyObject *callback;
|
||||
size_t i = 0, key_start = 0, key_length = 0, val_start = 0, val_length = 0;
|
||||
if (!PyArg_ParseTuple(args, "s*O", &buf, &callback)) return NULL;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ serialize_string_tuple(PyObject *src) {
|
|||
const char *pysrc = PyUnicode_AsUTF8(PyTuple_GET_ITEM(src, i));
|
||||
if (!pysrc) {
|
||||
PyErr_Clear();
|
||||
DECREF_AFTER_FUNCTION PyObject *u8 = PyUnicode_AsEncodedString(PyTuple_GET_ITEM(src, i), "UTF-8", "ignore");
|
||||
RAII_PyObject(u8, PyUnicode_AsEncodedString(PyTuple_GET_ITEM(src, i), "UTF-8", "ignore"));
|
||||
if (!u8) { PyErr_Print(); fatal("couldn't parse command line"); }
|
||||
ans[i] = calloc(PyBytes_GET_SIZE(u8) + 1, sizeof(char));
|
||||
if (ans[i] == NULL) fatal("Out of memory");
|
||||
|
|
|
|||
|
|
@ -683,7 +683,7 @@ - (BOOL)openFileURLs:(NSPasteboard*)pasteboard
|
|||
if (OPT(macos_menubar_title_max_length) > 0 && PyUnicode_GetLength(pytitle) > OPT(macos_menubar_title_max_length)) {
|
||||
static char fmt[64];
|
||||
snprintf(fmt, sizeof(fmt), "%%%ld.%ldU%%s", OPT(macos_menubar_title_max_length), OPT(macos_menubar_title_max_length));
|
||||
DECREF_AFTER_FUNCTION PyObject *st = PyUnicode_FromFormat(fmt, pytitle, "…");
|
||||
RAII_PyObject(st, PyUnicode_FromFormat(fmt, pytitle, "…"));
|
||||
if (st) title = @(PyUnicode_AsUTF8(st));
|
||||
} else {
|
||||
title = @(PyUnicode_AsUTF8(pytitle));
|
||||
|
|
|
|||
|
|
@ -488,7 +488,7 @@ color_as_int(Color *self) {
|
|||
|
||||
static PyObject*
|
||||
color_truediv(Color *self, PyObject *divisor) {
|
||||
DECREF_AFTER_FUNCTION PyObject *o = PyNumber_Float(divisor);
|
||||
RAII_PyObject(o, PyNumber_Float(divisor));
|
||||
if (o == NULL) return NULL;
|
||||
double r = self->color.r, g = self->color.g, b = self->color.b, a = self->color.a;
|
||||
double d = PyFloat_AS_DOUBLE(o) * 255.;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ static PyObject*
|
|||
process_group_map(void) {
|
||||
int num_of_processes = proc_listallpids(NULL, 0);
|
||||
size_t bufsize = sizeof(pid_t) * (num_of_processes + 1024);
|
||||
FREE_AFTER_FUNCTION pid_t *buf = malloc(bufsize);
|
||||
RAII_ALLOC(pid_t, buf, malloc(bufsize));
|
||||
if (!buf) return PyErr_NoMemory();
|
||||
num_of_processes = proc_listallpids(buf, (int)bufsize);
|
||||
PyObject *ans = PyTuple_New(num_of_processes);
|
||||
|
|
@ -79,7 +79,7 @@ redirect_std_streams(PyObject UNUSED *self, PyObject *args) {
|
|||
static PyObject*
|
||||
pybase64_encode(PyObject UNUSED *self, PyObject *args) {
|
||||
int add_padding = 0;
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer view = {0};
|
||||
RAII_PY_BUFFER(view);
|
||||
if (!PyArg_ParseTuple(args, "s*|p", &view, &add_padding)) return NULL;
|
||||
size_t sz = required_buffer_size_for_base64_encode(view.len);
|
||||
PyObject *ans = PyBytes_FromStringAndSize(NULL, sz);
|
||||
|
|
@ -91,7 +91,7 @@ pybase64_encode(PyObject UNUSED *self, PyObject *args) {
|
|||
|
||||
static PyObject*
|
||||
pybase64_decode(PyObject UNUSED *self, PyObject *args) {
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer view = {0};
|
||||
RAII_PY_BUFFER(view);
|
||||
if (!PyArg_ParseTuple(args, "s*", &view)) return NULL;
|
||||
size_t sz = required_buffer_size_for_base64_decode(view.len);
|
||||
PyObject *ans = PyBytes_FromStringAndSize(NULL, sz);
|
||||
|
|
|
|||
|
|
@ -46,10 +46,10 @@
|
|||
void log_error(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
#define fatal(...) { log_error(__VA_ARGS__); exit(EXIT_FAILURE); }
|
||||
static inline void cleanup_free(void *p) { free(*(void**)p); }
|
||||
#define FREE_AFTER_FUNCTION __attribute__((cleanup(cleanup_free)))
|
||||
#define RAII_ALLOC(type, name, initializer) __attribute__((cleanup(cleanup_free))) type *name = initializer
|
||||
static inline void cleanup_decref(PyObject **p) { if(*p) { Py_DECREF(*p); *p = NULL;} }
|
||||
#define DECREF_AFTER_FUNCTION __attribute__((cleanup(cleanup_decref)))
|
||||
#define FREE_BUFFER_AFTER_FUNCTION __attribute__((cleanup(PyBuffer_Release)))
|
||||
#define RAII_PyObject(name, initializer) __attribute__((cleanup(cleanup_decref))) PyObject *name = initializer
|
||||
#define RAII_PY_BUFFER(name) __attribute__((cleanup(PyBuffer_Release))) Py_buffer name = {0}
|
||||
|
||||
typedef unsigned long long id_type;
|
||||
typedef uint32_t char_type;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ open_cache_file_without_tmpfile(const char *cache_path) {
|
|||
int fd = -1;
|
||||
static const char template[] = "%s/disk-cache-XXXXXXXXXXXX";
|
||||
const size_t sz = strlen(cache_path) + sizeof(template) + 4;
|
||||
FREE_AFTER_FUNCTION char *buf = calloc(1, sz);
|
||||
RAII_ALLOC(char, buf, calloc(1, sz));
|
||||
if (!buf) { errno = ENOMEM; return -1; }
|
||||
snprintf(buf, sz - 1, template, cache_path);
|
||||
while (fd < 0) {
|
||||
|
|
@ -132,8 +132,8 @@ typedef struct {
|
|||
static void
|
||||
defrag(DiskCache *self) {
|
||||
int new_cache_file = -1;
|
||||
FREE_AFTER_FUNCTION DefragEntry *defrag_entries = NULL;
|
||||
AutoFreeFastFileCopyBuffer fcb = {0};
|
||||
RAII_ALLOC(DefragEntry, defrag_entries, NULL);
|
||||
RAII_FreeFastFileCopyBuffer(fcb);
|
||||
bool lock_released = false, ok = false;
|
||||
|
||||
off_t size_on_disk = size_of_cache_file(self);
|
||||
|
|
@ -441,7 +441,7 @@ add_to_disk_cache(PyObject *self_, const void *key, size_t key_sz, const void *d
|
|||
if (!ensure_state(self)) return false;
|
||||
if (key_sz > MAX_KEY_SIZE) { PyErr_SetString(PyExc_KeyError, "cache key is too long"); return false; }
|
||||
CacheEntry *s = NULL;
|
||||
FREE_AFTER_FUNCTION uint8_t *copied_data = malloc(data_sz);
|
||||
RAII_ALLOC(uint8_t, copied_data, malloc(data_sz));
|
||||
if (!copied_data) { PyErr_NoMemory(); return false; }
|
||||
memcpy(copied_data, data, data_sz);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ typedef struct FastFileCopyBuffer {
|
|||
static inline void
|
||||
free_fast_file_copy_buffer(FastFileCopyBuffer *fcb) { free(fcb->buf); fcb->buf = NULL; }
|
||||
|
||||
#define FREE_FCB_AFTER_FUNCTION __attribute__ ((__cleanup__(free_fast_file_copy_buffer)))
|
||||
#define AutoFreeFastFileCopyBuffer FREE_FCB_AFTER_FUNCTION FastFileCopyBuffer
|
||||
#define RAII_FreeFastFileCopyBuffer(name) __attribute__ ((__cleanup__(free_fast_file_copy_buffer))) FastFileCopyBuffer name = {0}
|
||||
|
||||
bool copy_between_files(int infd, int outfd, off_t in_pos, size_t len, FastFileCopyBuffer *fcb);
|
||||
|
|
|
|||
|
|
@ -1527,7 +1527,7 @@ sprite_map_set_layout(PyObject UNUSED *self, PyObject *args) {
|
|||
static PyObject*
|
||||
test_sprite_position_for(PyObject UNUSED *self, PyObject *args) {
|
||||
int error;
|
||||
FREE_AFTER_FUNCTION glyph_index *glyphs = calloc(PyTuple_GET_SIZE(args), sizeof(glyph_index));
|
||||
RAII_ALLOC(glyph_index, glyphs, calloc(PyTuple_GET_SIZE(args), sizeof(glyph_index)));
|
||||
for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(args); i++) {
|
||||
if (!PyLong_Check(PyTuple_GET_ITEM(args, i))) {
|
||||
PyErr_SetString(PyExc_TypeError, "glyph indices must be integers");
|
||||
|
|
|
|||
|
|
@ -494,14 +494,14 @@ typedef struct TempFontData {
|
|||
FT_UInt orig_sz;
|
||||
} TempFontData;
|
||||
|
||||
static void cleanup_resize(void *p) {
|
||||
TempFontData *f = p;
|
||||
static void
|
||||
cleanup_resize(TempFontData *f) {
|
||||
if (f->face && f->face->freetype) {
|
||||
f->face->pixel_size = f->orig_sz;
|
||||
FT_Set_Pixel_Sizes(f->face->freetype, f->orig_sz, f->orig_sz);
|
||||
}
|
||||
}
|
||||
#define RESIZE_AFTER_FUNCTION __attribute__((cleanup(cleanup_resize)))
|
||||
#define RAII_TempFontData(name) __attribute__((cleanup(cleanup_resize))) TempFontData name = {0}
|
||||
|
||||
static void*
|
||||
report_freetype_error_for_char(int error, char ch, const char *operation) {
|
||||
|
|
@ -515,7 +515,7 @@ uint8_t*
|
|||
render_single_ascii_char_as_mask(FreeTypeRenderCtx ctx_, const char ch, size_t *result_width, size_t *result_height) {
|
||||
RenderCtx *ctx = (RenderCtx*)ctx_;
|
||||
if (!ctx->created) { PyErr_SetString(PyExc_RuntimeError, "freetype render ctx not created"); return NULL; }
|
||||
RESIZE_AFTER_FUNCTION TempFontData temp = {0};
|
||||
RAII_TempFontData(temp);
|
||||
Face *face = &main_face;
|
||||
int glyph_index = FT_Get_Char_Index(face->freetype, ch);
|
||||
if (!glyph_index) { PyErr_Format(PyExc_KeyError, "character %c not found in font", ch); return NULL; }
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ update_menu_bar_title(PyObject *title UNUSED) {
|
|||
#ifdef __APPLE__
|
||||
static char buf[2048];
|
||||
strip_csi_(PyUnicode_AsUTF8(title), buf, arraysz(buf));
|
||||
DECREF_AFTER_FUNCTION PyObject *stitle = PyUnicode_FromString(buf);
|
||||
RAII_PyObject(stitle, PyUnicode_FromString(buf));
|
||||
cocoa_update_menu_bar_title(stitle);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1836,7 +1836,7 @@ strip_csi(PyObject *self UNUSED, PyObject *src) {
|
|||
Py_ssize_t sz;
|
||||
const char *title = PyUnicode_AsUTF8AndSize(src, &sz);
|
||||
if (!title) return NULL;
|
||||
FREE_AFTER_FUNCTION char *buf = malloc(sz + 1);
|
||||
RAII_ALLOC(char, buf, malloc(sz + 1));
|
||||
if (!buf) { return PyErr_NoMemory(); }
|
||||
strip_csi_(title, buf, sz + 1);
|
||||
return PyUnicode_FromString(buf);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ PyTypeObject GraphicsManager_Type;
|
|||
|
||||
#define DEFAULT_STORAGE_LIMIT 320u * (1024u * 1024u)
|
||||
#define REPORT_ERROR(...) { log_error(__VA_ARGS__); }
|
||||
#define FREE_CFD_AFTER_FUNCTION __attribute__((cleanup(cfd_free)))
|
||||
#define RAII_CoalescedFrameData(name, initializer) __attribute__((cleanup(cfd_free))) CoalescedFrameData name = initializer
|
||||
|
||||
// caching {{{
|
||||
#define CACHE_KEY_BUFFER_SIZE 32
|
||||
|
|
@ -424,7 +424,7 @@ load_image_data(GraphicsManager *self, Image *img, const GraphicsCommand *g, con
|
|||
else fd = safe_open(fname, O_CLOEXEC | O_RDONLY | O_NONBLOCK, 0); // O_NONBLOCK so that opening a FIFO pipe does not block
|
||||
if (fd == -1) ABRT("EBADF", "Failed to open file for graphics transmission with error: [%d] %s", errno, strerror(errno));
|
||||
if (global_state.boss && transmission_type != 's') {
|
||||
DECREF_AFTER_FUNCTION PyObject *cret_ = PyObject_CallMethod(global_state.boss, "is_ok_to_read_image_file", "si", fname, fd);
|
||||
RAII_PyObject(cret_, PyObject_CallMethod(global_state.boss, "is_ok_to_read_image_file", "si", fname, fd));
|
||||
if (cret_ == NULL) {
|
||||
PyErr_Print();
|
||||
ABRT("EBADF", "Failed to check file for read permission");
|
||||
|
|
@ -1496,7 +1496,7 @@ scan_active_animations(GraphicsManager *self, const monotonic_t now, monotonic_t
|
|||
|
||||
// {{{ composition a=c
|
||||
static void
|
||||
cfd_free(void *p) { free(((CoalescedFrameData*)p)->buf); }
|
||||
cfd_free(CoalescedFrameData *p) { free((p)->buf); p->buf = NULL; }
|
||||
|
||||
static void
|
||||
handle_compose_command(GraphicsManager *self, bool *is_dirty, const GraphicsCommand *g, Image *img) {
|
||||
|
|
@ -1530,12 +1530,12 @@ handle_compose_command(GraphicsManager *self, bool *is_dirty, const GraphicsComm
|
|||
}
|
||||
}
|
||||
|
||||
FREE_CFD_AFTER_FUNCTION CoalescedFrameData src_data = get_coalesced_frame_data(self, img, src_frame);
|
||||
RAII_CoalescedFrameData(src_data, get_coalesced_frame_data(self, img, src_frame));
|
||||
if (!src_data.buf) {
|
||||
set_command_failed_response("EINVAL", "Failed to get data for src frame: %u", g->frame_number - 1);
|
||||
return;
|
||||
}
|
||||
FREE_CFD_AFTER_FUNCTION CoalescedFrameData dest_data = get_coalesced_frame_data(self, img, dest_frame);
|
||||
RAII_CoalescedFrameData(dest_data, get_coalesced_frame_data(self, img, dest_frame));
|
||||
if (!dest_data.buf) {
|
||||
set_command_failed_response("EINVAL", "Failed to get data for destination frame: %u", g->other_frame_number - 1);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@
|
|||
#endif
|
||||
|
||||
static void cleanup_free(void *p) { free(*(void**) p); }
|
||||
#define FREE_AFTER_FUNCTION __attribute__((cleanup(cleanup_free)))
|
||||
#define RAII_ALLOC(type, name, initializer) __attribute__((cleanup(cleanup_free))) type *name = initializer
|
||||
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
static bool
|
||||
safe_realpath(const char* src, char *buf, size_t buf_sz) {
|
||||
FREE_AFTER_FUNCTION char* ans = realpath(src, NULL);
|
||||
RAII_ALLOC(char, ans, realpath(src, NULL));
|
||||
if (ans == NULL) return false;
|
||||
snprintf(buf, buf_sz, "%s", ans);
|
||||
return true;
|
||||
|
|
@ -83,8 +83,8 @@ canonicalize_path(const char *srcpath, char *dstpath, size_t sz) {
|
|||
// remove . and .. path segments
|
||||
bool ok = false;
|
||||
size_t plen = strlen(srcpath) + 1, chk;
|
||||
FREE_AFTER_FUNCTION char *wtmp = malloc(plen);
|
||||
FREE_AFTER_FUNCTION char **tokv = malloc(sizeof(char*) * plen);
|
||||
RAII_ALLOC(char, wtmp, malloc(plen));
|
||||
RAII_ALLOC(char*, tokv, malloc(sizeof(char*) * plen));
|
||||
if (!wtmp || !tokv) goto end;
|
||||
char *s, *tok, *sav;
|
||||
bool relpath = *srcpath != '/';
|
||||
|
|
@ -360,7 +360,7 @@ int main(int argc, char *argv[], char* envp[]) {
|
|||
if (!ensure_working_stdio()) return 1;
|
||||
char exe[PATH_MAX+1] = {0};
|
||||
char exe_dir_buf[PATH_MAX+1] = {0};
|
||||
FREE_AFTER_FUNCTION const char *lc_ctype = NULL;
|
||||
RAII_ALLOC(const char, lc_ctype, NULL);
|
||||
#ifdef __APPLE__
|
||||
lc_ctype = getenv("LC_CTYPE");
|
||||
if (lc_ctype) lc_ctype = strdup(lc_ctype);
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ as_text(LineBuf *self, PyObject *args) {
|
|||
|
||||
static PyObject*
|
||||
__str__(LineBuf *self) {
|
||||
DECREF_AFTER_FUNCTION PyObject *lines = PyTuple_New(self->ynum);
|
||||
RAII_PyObject(lines, PyTuple_New(self->ynum));
|
||||
if (lines == NULL) return PyErr_NoMemory();
|
||||
for (index_type i = 0; i < self->ynum; i++) {
|
||||
init_line(self, self->line, self->line_map[i]);
|
||||
|
|
@ -477,7 +477,7 @@ __str__(LineBuf *self) {
|
|||
if (t == NULL) return NULL;
|
||||
PyTuple_SET_ITEM(lines, i, t);
|
||||
}
|
||||
DECREF_AFTER_FUNCTION PyObject *sep = PyUnicode_FromString("\n");
|
||||
RAII_PyObject(sep, PyUnicode_FromString("\n"));
|
||||
return PyUnicode_Join(sep, lines);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -853,9 +853,9 @@ as_text_generic(PyObject *args, void *container, get_line_func get_line, index_t
|
|||
int as_ansi = 0, insert_wrap_markers = 0;
|
||||
if (!PyArg_ParseTuple(args, "O|pp", &callback, &as_ansi, &insert_wrap_markers)) return NULL;
|
||||
PyObject *t = NULL;
|
||||
DECREF_AFTER_FUNCTION PyObject *nl = PyUnicode_FromString("\n");
|
||||
DECREF_AFTER_FUNCTION PyObject *cr = PyUnicode_FromString("\r");
|
||||
DECREF_AFTER_FUNCTION PyObject *sgr_reset = PyUnicode_FromString("\x1b[m");
|
||||
RAII_PyObject(nl, PyUnicode_FromString("\n"));
|
||||
RAII_PyObject(cr, PyUnicode_FromString("\r"));
|
||||
RAII_PyObject(sgr_reset, PyUnicode_FromString("\x1b[m"));
|
||||
if (nl == NULL || cr == NULL || sgr_reset == NULL) return NULL;
|
||||
const GPUCell *prev_cell = NULL;
|
||||
ansibuf->active_hyperlink_id = 0;
|
||||
|
|
|
|||
|
|
@ -192,18 +192,18 @@ text_composition_strategy(PyObject *val, Options *opts) {
|
|||
else if (PyUnicode_CompareWithASCIIString(val, "legacy") == 0) {
|
||||
opts->text_old_gamma = true;
|
||||
} else {
|
||||
DECREF_AFTER_FUNCTION PyObject *parts = PyUnicode_Split(val, NULL, 2);
|
||||
RAII_PyObject(parts, PyUnicode_Split(val, NULL, 2));
|
||||
int size = PyList_GET_SIZE(parts);
|
||||
if (size < 1 || 2 < size) { PyErr_SetString(PyExc_ValueError, "text_rendering_strategy must be of the form number:[number]"); return; }
|
||||
|
||||
if (size > 0) {
|
||||
DECREF_AFTER_FUNCTION PyObject *ga = PyFloat_FromString(PyList_GET_ITEM(parts, 0));
|
||||
RAII_PyObject(ga, PyFloat_FromString(PyList_GET_ITEM(parts, 0)));
|
||||
if (PyErr_Occurred()) return;
|
||||
opts->text_gamma_adjustment = MAX(0.01f, PyFloat_AsFloat(ga));
|
||||
}
|
||||
|
||||
if (size > 1) {
|
||||
DECREF_AFTER_FUNCTION PyObject *contrast = PyFloat_FromString(PyList_GET_ITEM(parts, 1));
|
||||
RAII_PyObject(contrast, PyFloat_FromString(PyList_GET_ITEM(parts, 1)));
|
||||
if (PyErr_Occurred()) return;
|
||||
opts->text_contrast = MAX(0.0f, PyFloat_AsFloat(contrast));
|
||||
opts->text_contrast = MIN(100.0f, opts->text_contrast);
|
||||
|
|
|
|||
|
|
@ -1581,7 +1581,7 @@ do_parse_bytes(Screen *screen, const uint8_t *read_buf, const size_t read_buf_sz
|
|||
PyObject*
|
||||
FNAME(parse_bytes)(PyObject UNUSED *self, PyObject *args) {
|
||||
PyObject *dump_callback = NULL;
|
||||
FREE_BUFFER_AFTER_FUNCTION Py_buffer pybuf = {0};
|
||||
RAII_PY_BUFFER(pybuf);
|
||||
Screen *screen;
|
||||
#ifdef DUMP_COMMANDS
|
||||
if (!PyArg_ParseTuple(args, "OO!y*", &dump_callback, &Screen_Type, &screen, &pybuf)) return NULL;
|
||||
|
|
|
|||
|
|
@ -2049,9 +2049,9 @@ shell_prompt_marking(Screen *self, PyObject *data) {
|
|||
PromptKind pk = PROMPT_START;
|
||||
self->prompt_settings.redraws_prompts_at_all = 1;
|
||||
if (PyUnicode_FindChar(data, ';', 0, PyUnicode_GET_LENGTH(data), 1)) {
|
||||
DECREF_AFTER_FUNCTION PyObject *sep = PyUnicode_FromString(";");
|
||||
RAII_PyObject(sep, PyUnicode_FromString(";"));
|
||||
if (sep) {
|
||||
DECREF_AFTER_FUNCTION PyObject *parts = PyUnicode_Split(data, sep, -1);
|
||||
RAII_PyObject(parts, PyUnicode_Split(data, sep, -1));
|
||||
if (parts) parse_prompt_mark(self, parts, &pk);
|
||||
}
|
||||
}
|
||||
|
|
@ -2707,8 +2707,8 @@ ansi_for_range(Screen *self, const Selection *sel, bool insert_newlines, bool st
|
|||
IterationData idata;
|
||||
iteration_data(self, sel, &idata, -self->historybuf->count, false);
|
||||
int limit = MIN((int)self->lines, idata.y_limit);
|
||||
DECREF_AFTER_FUNCTION PyObject *ans = PyTuple_New(limit - idata.y + 1);
|
||||
DECREF_AFTER_FUNCTION PyObject *nl = PyUnicode_FromString("\n");
|
||||
RAII_PyObject(ans, PyTuple_New(limit - idata.y + 1));
|
||||
RAII_PyObject(nl, PyUnicode_FromString("\n"));
|
||||
if (!ans || !nl) return NULL;
|
||||
ANSIBuf output = {0};
|
||||
const GPUCell *prev_cell = NULL;
|
||||
|
|
@ -2941,7 +2941,7 @@ screen_update_overlay_text(Screen *self, const char *utf8_text) {
|
|||
if (!text) return;
|
||||
Py_XDECREF(self->overlay_line.overlay_text);
|
||||
// Calculate the total number of cells for initial overlay cursor position
|
||||
DECREF_AFTER_FUNCTION PyObject *text_len = wcswidth_std(NULL, text);
|
||||
RAII_PyObject(text_len, wcswidth_std(NULL, text));
|
||||
self->overlay_line.overlay_text = text;
|
||||
self->overlay_line.is_active = true;
|
||||
self->overlay_line.is_dirty = true;
|
||||
|
|
@ -3230,8 +3230,8 @@ find_cmd_output(Screen *self, OutputOffset *oo, index_type start_screen_y, unsig
|
|||
static PyObject*
|
||||
cmd_output(Screen *self, PyObject *args) {
|
||||
unsigned int which = 0;
|
||||
DECREF_AFTER_FUNCTION PyObject *which_args = PyTuple_GetSlice(args, 0, 1);
|
||||
DECREF_AFTER_FUNCTION PyObject *as_text_args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
|
||||
RAII_PyObject(which_args, PyTuple_GetSlice(args, 0, 1));
|
||||
RAII_PyObject(as_text_args, PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args)));
|
||||
if (!which_args || !as_text_args) return NULL;
|
||||
if (!PyArg_ParseTuple(which_args, "I", &which)) return NULL;
|
||||
if (self->linebuf != self->main_linebuf) Py_RETURN_NONE;
|
||||
|
|
@ -3280,7 +3280,7 @@ cmd_output(Screen *self, PyObject *args) {
|
|||
return NULL;
|
||||
}
|
||||
if (found) {
|
||||
DECREF_AFTER_FUNCTION PyObject *ret = as_text_generic(as_text_args, &oo, get_line_from_offset, oo.num_lines, &self->as_ansi_buf, false);
|
||||
RAII_PyObject(ret, as_text_generic(as_text_args, &oo, get_line_from_offset, oo.num_lines, &self->as_ansi_buf, false));
|
||||
if (!ret) return NULL;
|
||||
}
|
||||
if (oo.reached_upper_limit && self->linebuf == self->main_linebuf && OPT(scrollback_pager_history_size) > 0) Py_RETURN_TRUE;
|
||||
|
|
@ -4166,7 +4166,7 @@ paste_(Screen *self, PyObject *bytes, bool allow_bracketed_paste) {
|
|||
if (PyBytes_Check(bytes)) {
|
||||
data = PyBytes_AS_STRING(bytes); sz = PyBytes_GET_SIZE(bytes);
|
||||
} else if (PyMemoryView_Check(bytes)) {
|
||||
DECREF_AFTER_FUNCTION PyObject *mv = PyMemoryView_GetContiguous(bytes, PyBUF_READ, PyBUF_C_CONTIGUOUS);
|
||||
RAII_PyObject(mv, PyMemoryView_GetContiguous(bytes, PyBUF_READ, PyBUF_C_CONTIGUOUS));
|
||||
if (mv == NULL) return NULL;
|
||||
Py_buffer *buf = PyMemoryView_GET_BUFFER(mv);
|
||||
data = buf->buf;
|
||||
|
|
|
|||
|
|
@ -1047,7 +1047,7 @@ draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_bu
|
|||
|
||||
static bool
|
||||
attach_shaders(PyObject *sources, GLuint program_id, GLenum shader_type) {
|
||||
FREE_AFTER_FUNCTION const GLchar * * c_sources = calloc(sizeof(char*), PyTuple_GET_SIZE(sources));
|
||||
RAII_ALLOC(const GLchar*, c_sources, calloc(sizeof(GLchar*), PyTuple_GET_SIZE(sources)));
|
||||
for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(sources); i++) {
|
||||
PyObject *temp = PyTuple_GET_ITEM(sources, i);
|
||||
if (!PyUnicode_Check(temp)) { PyErr_SetString(PyExc_TypeError, "shaders must be strings"); return false; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue