forked from paulross/PythonExtensionPatterns
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscratch.c
More file actions
115 lines (80 loc) · 2.31 KB
/
scratch.c
File metadata and controls
115 lines (80 loc) · 2.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//
// scratch.c
// PythonExtensionPatterns
//
// Created by Paul Ross on 04/04/2015.
// Copyright (c) 2015 Paul Ross. All rights reserved.
//
#include "Python.h"
#include <stdio.h>
#include <stdlib.h>
void leak() {
char *p;
p = malloc(1024);
}
void access_after_free() {
char *p;
p = malloc(1024);
free(p);
p[8] = 'A';
printf("%c", p[8]);
}
#include "Python.h"
void py_leak() {
PyObject *pObj = NULL;
/* Object creation, ref count = 1. */
pObj = PyBytes_FromString("Hello world\n");
PyObject_Print(pObj, stdout, 0);
/* Object still has ref count = 1. */
}
#include "Python.h"
void py_access_after_free() {
PyObject *pObj = NULL;
/* Object creation, ref count = 1. */
pObj = PyBytes_FromString("Hello world\n");
PyObject_Print(pObj, stdout, 0);
/* ref count = 0 so object deallocated. */
Py_DECREF(pObj);
/* Now use pObj... */
PyObject_Print(pObj, stdout, 0);
}
void py_caller_access_after_free(PyObject *pObj) {
/* ... code here ... */
Py_DECREF(pObj);
/* ... more code here ... */
}
PyObject *bad_incref(PyObject *pObj) {
Py_INCREF(pObj);
int error = 0;
/* ... a metric ton of code here ... */
if (error) {
/* No matching Py_DECREF, pObj is leaked. */
return NULL;
}
/* ... more code here ... */
Py_DECREF(pObj);
Py_RETURN_NONE;
}
void bad_steal() {
PyObject *v, *r;
r = PyTuple_New(3); /* New reference. */
v = PyLong_FromLong(1L); /* New reference. */
PyTuple_SetItem(r, 0, v); /* r takes ownership of the reference. */
Py_DECREF(v); /* Now we are interfering with r's internals. */
/* Two common patterns to avoid this, either: */
v = PyLong_FromLong(1L); /* New reference. */
PyTuple_SetItem(r, 0, v); /* r takes ownership of the reference. */
v = NULL;
/* Or: */
PyTuple_SetItem(r, 0, PyLong_FromLong(1L));
}
static PyObject *pop_and_print_BAD(PyObject *pList) {
PyObject *pLast;
pLast = PyList_GetItem(pList, PyList_Size(pList) - 1);
fprintf(stdout, "Ref count was: %zd\n", pLast->ob_refcnt);
do_something(pList); /* Dragons ahoy me hearties! */
fprintf(stdout, "Ref count now: %zd\n", pLast->ob_refcnt);
PyObject_Print(pLast, stdout, 0);
fprintf(stdout, "\n");
Py_RETURN_NONE;
}