Skip to content

Commit

Permalink
Merge pull request #179 from hpyproject/feature/raise-value-error-whe…
Browse files Browse the repository at this point in the history
…n-hpybytes-from-string-and-size-called-with-null-pointer

Raise ValueError when HPyBytes_FromStringAndSize is called with null pointer.
  • Loading branch information
hodgestar authored Mar 4, 2021
2 parents f45c472 + 7988c51 commit b02b6fd
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 5 deletions.
5 changes: 0 additions & 5 deletions hpy/devel/include/common/autogen_impl.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions hpy/devel/include/common/implementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,21 @@ HPyAPI_STORAGE int
_HPy_IMPL_NAME(Err_Occurred)(HPyContext ctx) {
return PyErr_Occurred() ? 1 : 0;
}

/* bytes.h */

HPyAPI_STORAGE HPy
_HPy_IMPL_NAME(Bytes_FromStringAndSize)(HPyContext ctx, const char *v, HPy_ssize_t len)
{
if (v == NULL) {
// The CPython API allows passing a null pointer to
// PyBytes_FromStringAndSize and returns uninitialized memory of the
// requested size which can then be initialized after the call.
// In HPy the underlying memory is opaque and so cannot be initialized
// after the call and so we raise an error instead.
HPyErr_SetString(ctx, ctx->h_ValueError,
"NULL char * passed to HPyBytes_FromStringAndSize");
return HPy_NULL;
}
return _py2h(PyBytes_FromStringAndSize(v, len));
}
1 change: 1 addition & 0 deletions hpy/tools/autogen/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ def _visit_hpyslot_slot(self, node):
'_HPy_Dump': None,
'HPy_Type': 'PyObject_Type',
'HPy_TypeCheck': None,
'HPyBytes_FromStringAndSize': None,
}


Expand Down
61 changes: 61 additions & 0 deletions test/test_hpybytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,64 @@ def test_AS_STRING(self):
@INIT
""")
assert mod.f(b'ABC') == 100*ord('A') + 10*ord('B') + ord('C')

def test_FromString(self):
mod = self.make_module("""
HPyDef_METH(f, "f", f_impl, HPyFunc_O)
static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
{
char *buf;
buf = HPyBytes_AsString(ctx, arg);
return HPyBytes_FromString(ctx, buf);
}
@EXPORT(f)
@INIT
""")
assert mod.f(b"aaa") == b"aaa"
assert mod.f(b"") == b""

def test_FromStringAndSize(self):
import pytest
mod = self.make_module("""
HPyDef_METH(f, "f", f_impl, HPyFunc_VARARGS)
static HPy f_impl(HPyContext ctx, HPy self, HPy *args,
HPy_ssize_t nargs)
{
HPy src;
long len;
char *buf;
if (!HPyArg_Parse(ctx, NULL, args, nargs, "Ol", &src, &len)) {
return HPy_NULL;
}
buf = HPyBytes_AsString(ctx, src);
return HPyBytes_FromStringAndSize(ctx, buf, len);
}
HPyDef_METH(f_null, "f_null", f_null_impl, HPyFunc_VARARGS)
static HPy f_null_impl(HPyContext ctx, HPy self, HPy *args,
HPy_ssize_t nargs)
{
long len;
if (!HPyArg_Parse(ctx, NULL, args, nargs, "l", &len)) {
return HPy_NULL;
}
return HPyBytes_FromStringAndSize(ctx, NULL, len);
}
@EXPORT(f)
@EXPORT(f_null)
@INIT
""")
assert mod.f(b"aaa", 3) == b"aaa"
assert mod.f(b"abc", 2) == b"ab"
assert mod.f(b"", 0) == b""
with pytest.raises(SystemError):
# negative size passed to HPyBytes_FromStringAndSize
mod.f(b"abc", -1)
for i in (-1, 0, 1):
with pytest.raises(ValueError) as err:
mod.f_null(i)
assert str(err.value) == (
"NULL char * passed to HPyBytes_FromStringAndSize")

0 comments on commit b02b6fd

Please sign in to comment.