Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
PyPy
cffi
Commits
57afc244cbc2
Commit
67e69ada
authored
Jul 06, 2015
by
Armin Rigo
Browse files
Explicitly protect against variables that end up resolving at address NULL,
which can occur in random cases like test_macro_var_callback
parent
307f969f209f
Changes
3
Hide whitespace changes
Inline
Side-by-side
c/cglob.c
View file @
57afc244
...
...
@@ -4,6 +4,7 @@ typedef void *(*gs_fetch_addr_fn)(void);
typedef
struct
{
PyObject_HEAD
PyObject
*
gs_name
;
CTypeDescrObject
*
gs_type
;
char
*
gs_data
;
gs_fetch_addr_fn
gs_fetch_addr
;
...
...
@@ -12,6 +13,7 @@ typedef struct {
static
void
glob_support_dealloc
(
GlobSupportObject
*
gs
)
{
Py_DECREF
(
gs
->
gs_name
);
Py_DECREF
(
gs
->
gs_type
);
PyObject_Del
(
gs
);
}
...
...
@@ -41,14 +43,16 @@ static PyTypeObject GlobSupport_Type = {
#define GlobSupport_Check(ob) (Py_TYPE(ob) == &GlobSupport_Type)
static
PyObject
*
make_global_var
(
CTypeDescrObject
*
type
,
char
*
addr
,
gs_fetch_addr_fn
fetch_addr
)
static
PyObject
*
make_global_var
(
PyObject
*
name
,
CTypeDescrObject
*
type
,
char
*
addr
,
gs_fetch_addr_fn
fetch_addr
)
{
GlobSupportObject
*
gs
=
PyObject_New
(
GlobSupportObject
,
&
GlobSupport_Type
);
if
(
gs
==
NULL
)
return
NULL
;
Py_INCREF
(
name
);
Py_INCREF
(
type
);
gs
->
gs_name
=
name
;
gs
->
gs_type
=
type
;
gs
->
gs_data
=
addr
;
gs
->
gs_fetch_addr
=
fetch_addr
;
...
...
@@ -68,18 +72,27 @@ static void *fetch_global_var_addr(GlobSupportObject *gs)
save_errno
();
Py_END_ALLOW_THREADS
}
if
(
data
==
NULL
)
{
PyErr_Format
(
FFIError
,
"global variable '%s' is at address NULL"
,
PyText_AS_UTF8
(
gs
->
gs_name
));
return
NULL
;
}
return
data
;
}
static
PyObject
*
read_global_var
(
GlobSupportObject
*
gs
)
{
void
*
data
=
fetch_global_var_addr
(
gs
);
if
(
data
==
NULL
)
return
NULL
;
return
convert_to_object
(
data
,
gs
->
gs_type
);
}
static
int
write_global_var
(
GlobSupportObject
*
gs
,
PyObject
*
obj
)
{
void
*
data
=
fetch_global_var_addr
(
gs
);
if
(
data
==
NULL
)
return
-
1
;
return
convert_from_object
(
data
,
gs
->
gs_type
,
obj
);
}
...
...
@@ -91,7 +104,10 @@ static PyObject *cg_addressof_global_var(GlobSupportObject *gs)
return
NULL
;
data
=
fetch_global_var_addr
(
gs
);
x
=
new_simple_cdata
(
data
,
(
CTypeDescrObject
*
)
ptrtype
);
if
(
data
!=
NULL
)
x
=
new_simple_cdata
(
data
,
(
CTypeDescrObject
*
)
ptrtype
);
else
x
=
NULL
;
Py_DECREF
(
ptrtype
);
return
x
;
}
c/lib_obj.c
View file @
57afc244
...
...
@@ -324,7 +324,7 @@ static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name,
if
(
address
==
NULL
)
return
NULL
;
}
x
=
make_global_var
(
ct
,
address
,
NULL
);
x
=
make_global_var
(
name
,
ct
,
address
,
NULL
);
}
Py_DECREF
(
ct
);
break
;
...
...
@@ -335,7 +335,7 @@ static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name,
_CFFI_GETARG
(
g
->
type_op
));
if
(
ct
==
NULL
)
return
NULL
;
x
=
make_global_var
(
ct
,
NULL
,
(
gs_fetch_addr_fn
)
g
->
address
);
x
=
make_global_var
(
name
,
ct
,
NULL
,
(
gs_fetch_addr_fn
)
g
->
address
);
Py_DECREF
(
ct
);
break
;
...
...
testing/cffi1/test_recompiler.py
View file @
57afc244
...
...
@@ -1128,3 +1128,22 @@ def test_macro_var_callback():
assert
values
[
2
]
==
42
assert
p
[
-
1
]
==
41
assert
p
[
+
1
]
==
42
#
# if get_my_value raises or returns nonsense, the exception is printed
# to stderr like with any callback, but then the C expression 'my_value'
# expand to '*NULL'. We assume here that '&my_value' will return NULL
# without segfaulting, and check for NULL when accessing the variable.
@
ffi
.
callback
(
"int *(*)(void)"
)
def
get_my_value
():
raise
LookupError
lib
.
get_my_value
=
get_my_value
py
.
test
.
raises
(
ffi
.
error
,
getattr
,
lib
,
'my_value'
)
py
.
test
.
raises
(
ffi
.
error
,
setattr
,
lib
,
'my_value'
,
50
)
py
.
test
.
raises
(
ffi
.
error
,
ffi
.
addressof
,
lib
,
'my_value'
)
@
ffi
.
callback
(
"int *(*)(void)"
)
def
get_my_value
():
return
"hello"
lib
.
get_my_value
=
get_my_value
py
.
test
.
raises
(
ffi
.
error
,
getattr
,
lib
,
'my_value'
)
e
=
py
.
test
.
raises
(
ffi
.
error
,
setattr
,
lib
,
'my_value'
,
50
)
assert
str
(
e
.
value
)
==
"global variable 'my_value' is at address NULL"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment