[PATCH] v2v: linux: pass the root device when using SUSE's mkinitrd
by Pino Toscano
mkinitrd in SLE guests < 12 tries to get the root device by scanning the
fstab: this will fail, since v2v already remapped the devices from
hd*/sd* to vd* in the guest (including in its fstab).
Since we know what is the root device in the appliance, pass it to
mkinitrd directly, so it does not have to do guesswork.
Thanks to: Cédric Bosdonnat, for reporting the issue, and testing
the fix.
---
v2v/convert_linux.ml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml
index a1088b3..f8dfa00 100644
--- a/v2v/convert_linux.ml
+++ b/v2v/convert_linux.ml
@@ -517,7 +517,8 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
g#command [| "/sbin/mkinitrd";
"-m"; String.concat " " modules;
"-i"; initrd;
- "-k"; kernel.ki_vmlinuz |]
+ "-k"; kernel.ki_vmlinuz;
+ "-d"; inspect.i_root |]
)
)
else if family = `Debian_family then (
--
2.9.3
7 years, 7 months
[PATCH v2] RHBZ#1406906: check return value of Python object functions
by Matteo Cafasso
Verify the returned values of Python Object constructor functions
are not NULL before adding them to a collection.
This is particularly relevant when constructing Unicode strings in
Python 3 as they will return NULL if non UTF-8 characters are present.
Signed-off-by: Matteo Cafasso <noxdafox(a)gmail.com>
---
generator/python.ml | 102 ++++++++++++++++++++++++++---------------
python/handle.c | 36 ++++++++++++---
python/t/test830RHBZ1406906.py | 57 +++++++++++++++++++++++
3 files changed, 152 insertions(+), 43 deletions(-)
create mode 100644 python/t/test830RHBZ1406906.py
diff --git a/generator/python.ml b/generator/python.ml
index cf0829489..4cae24757 100644
--- a/generator/python.ml
+++ b/generator/python.ml
@@ -155,12 +155,20 @@ and generate_python_structs () =
pr "PyObject *\n";
pr "guestfs_int_py_put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
pr "{\n";
- pr " PyObject *list;\n";
+ pr " PyObject *list, *element;\n";
pr " size_t i;\n";
pr "\n";
pr " list = PyList_New (%ss->len);\n" typ;
- pr " for (i = 0; i < %ss->len; ++i)\n" typ;
- pr " PyList_SetItem (list, i, guestfs_int_py_put_%s (&%ss->val[i]));\n" typ typ;
+ pr " if (list == NULL)\n";
+ pr " return NULL;\n";
+ pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
+ pr " element = guestfs_int_py_put_%s (&%ss->val[i]);\n" typ typ;
+ pr " if (element == NULL) {\n";
+ pr " Py_CLEAR (list);\n";
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyList_SetItem (list, i, element);\n";
+ pr " }\n";
pr " return list;\n";
pr "};\n";
pr "#endif\n";
@@ -174,54 +182,72 @@ and generate_python_structs () =
pr "PyObject *\n";
pr "guestfs_int_py_put_%s (struct guestfs_%s *%s)\n" typ typ typ;
pr "{\n";
- pr " PyObject *dict;\n";
+ pr " PyObject *dict, *value;\n";
pr "\n";
pr " dict = PyDict_New ();\n";
+ pr " if (dict == NULL)\n";
+ pr " return NULL;\n";
List.iter (
function
| name, FString ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " guestfs_int_py_fromstring (%s->%s));\n"
- typ name
+ pr " value = guestfs_int_py_fromstring (%s->%s);" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FBuffer ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " guestfs_int_py_fromstringsize (%s->%s, %s->%s_len));\n"
- typ name typ name
+ pr " value = guestfs_int_py_fromstringsize (%s->%s, %s->%s_len);\n"
+ typ name typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FUUID ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " guestfs_int_py_fromstringsize (%s->%s, 32));\n"
- typ name
+ pr " value = guestfs_int_py_fromstringsize (%s->%s, 32);\n"
+ typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, (FBytes|FUInt64) ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromUnsignedLongLong (%s->%s);\n" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FInt64 ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromLongLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromLongLong (%s->%s);\n" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FUInt32 ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromUnsignedLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromUnsignedLong (%s->%s);\n" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FInt32 ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromLong (%s->%s);\n" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FOptPercent ->
- pr " if (%s->%s >= 0)\n" typ name;
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyFloat_FromDouble ((double) %s->%s));\n"
- typ name;
+ pr " if (%s->%s >= 0) {\n" typ name;
+ pr " value = PyFloat_FromDouble ((double) %s->%s);\n" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
+ pr " }\n";
pr " else {\n";
pr " Py_INCREF (Py_None);\n";
pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
pr " }\n"
| name, FChar ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " guestfs_int_py_fromstringsize (&%s->%s, 1));\n"
- typ name
+ pr " value = guestfs_int_py_fromstringsize (&%s->%s, 1);\n"
+ typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
) cols;
pr " return dict;\n";
+ pr " err:\n";
+ pr " Py_CLEAR (dict);\n";
+ pr " return NULL;\n";
pr "};\n";
pr "#endif\n";
pr "\n";
@@ -472,16 +498,20 @@ and generate_python_actions actions () =
pr " if (py_r == NULL) goto out;\n";
| RStringList _ ->
pr " py_r = guestfs_int_py_put_string_list (r);\n";
- pr " guestfs_int_free_string_list (r);\n"
+ pr " guestfs_int_free_string_list (r);\n";
+ pr " if (py_r == NULL) goto out;\n";
| RStruct (_, typ) ->
pr " py_r = guestfs_int_py_put_%s (r);\n" typ;
- pr " guestfs_free_%s (r);\n" typ
+ pr " guestfs_free_%s (r);\n" typ;
+ pr " if (py_r == NULL) goto out;\n";
| RStructList (_, typ) ->
pr " py_r = guestfs_int_py_put_%s_list (r);\n" typ;
- pr " guestfs_free_%s_list (r);\n" typ
+ pr " guestfs_free_%s_list (r);\n" typ;
+ pr " if (py_r == NULL) goto out;\n";
| RHashtable _ ->
pr " py_r = guestfs_int_py_put_table (r);\n";
- pr " guestfs_int_free_string_list (r);\n"
+ pr " guestfs_int_free_string_list (r);\n";
+ pr " if (py_r == NULL) goto out;\n";
| RBufferOut _ ->
pr " py_r = guestfs_int_py_fromstringsize (r, size);\n";
pr " free (r);\n";
diff --git a/python/handle.c b/python/handle.c
index 88024e184..d93f2f021 100644
--- a/python/handle.c
+++ b/python/handle.c
@@ -324,15 +324,23 @@ guestfs_int_py_get_string_list (PyObject *obj)
PyObject *
guestfs_int_py_put_string_list (char * const * const argv)
{
- PyObject *list;
+ PyObject *list, *item;
size_t argc, i;
for (argc = 0; argv[argc] != NULL; ++argc)
;
list = PyList_New (argc);
+ if (list == NULL)
+ return NULL;
for (i = 0; i < argc; ++i) {
- PyList_SetItem (list, i, guestfs_int_py_fromstring (argv[i]));
+ item = guestfs_int_py_fromstring (argv[i]);
+ if (item == NULL) {
+ Py_CLEAR (list);
+ return NULL;
+ }
+
+ PyList_SetItem (list, i, item);
}
return list;
@@ -341,21 +349,35 @@ guestfs_int_py_put_string_list (char * const * const argv)
PyObject *
guestfs_int_py_put_table (char * const * const argv)
{
- PyObject *list, *item;
+ PyObject *list, *tuple, *item;
size_t argc, i;
for (argc = 0; argv[argc] != NULL; ++argc)
;
list = PyList_New (argc >> 1);
+ if (list == NULL)
+ return NULL;
for (i = 0; i < argc; i += 2) {
- item = PyTuple_New (2);
- PyTuple_SetItem (item, 0, guestfs_int_py_fromstring (argv[i]));
- PyTuple_SetItem (item, 1, guestfs_int_py_fromstring (argv[i+1]));
- PyList_SetItem (list, i >> 1, item);
+ tuple = PyTuple_New (2);
+ if (tuple == NULL)
+ goto err;
+ item = guestfs_int_py_fromstring (argv[i]);
+ if (item == NULL)
+ goto err;
+ PyTuple_SetItem (tuple, 0, item);
+ item = guestfs_int_py_fromstring (argv[i+1]);
+ if (item == NULL)
+ goto err;
+ PyTuple_SetItem (tuple, 1, item);
+ PyList_SetItem (list, i >> 1, tuple);
}
return list;
+ err:
+ Py_CLEAR (list);
+ Py_CLEAR (tuple);
+ return NULL;
}
PyObject *
diff --git a/python/t/test830RHBZ1406906.py b/python/t/test830RHBZ1406906.py
new file mode 100644
index 000000000..17b875226
--- /dev/null
+++ b/python/t/test830RHBZ1406906.py
@@ -0,0 +1,57 @@
+# libguestfs Python bindings
+# Copyright (C) 2017 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import os
+import sys
+import shutil
+import tempfile
+import unittest
+
+import guestfs
+
+
+class Test830RHBZ1406906(unittest.TestCase):
+ def setUp(self):
+ self.tempdir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ shutil.rmtree(self.tempdir)
+
+ def test_rhbz1406906(self):
+ g = guestfs.GuestFS(python_return_dict=True)
+
+ g.add_drive_scratch(512 * 1024 * 1024)
+ g.launch()
+
+ g.part_disk("/dev/sda", "mbr")
+ g.mkfs("ext4", "/dev/sda1")
+ g.mount("/dev/sda1", "/")
+
+ self.assertEqual(g.find("/"), ['lost+found'])
+
+ # touch file with illegal unicode character
+ non_utf8_fname = "\udcd4"
+ open(os.path.join(self.tempdir, non_utf8_fname), "w").close()
+
+ g.copy_in(self.tempdir, "/")
+
+ if sys.version_info >= (3, 0):
+ with self.assertRaises(UnicodeDecodeError):
+ g.find("/") # segfault here on Python 3
+ elif sys.version_info >= (2, 0):
+ self.assertTrue(
+ any(path for path in g.find("/") if non_utf8_fname in path))
--
2.11.0
7 years, 7 months
[PATCH] python: improve few exceptions thrown on error
by Pino Toscano
Make use of functions and types that fit more, and that do the same job:
- use PyErr_NoMemory() on malloc failure
- use PyErr_SetFromErrno when setting an exception from an errno
- throw TypeError if not getting a list when required
---
python/handle.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/python/handle.c b/python/handle.c
index 88024e1..9746dca 100644
--- a/python/handle.c
+++ b/python/handle.c
@@ -237,7 +237,7 @@ guestfs_int_py_event_to_string (PyObject *self, PyObject *args)
str = guestfs_event_to_string (events);
if (str == NULL) {
- PyErr_SetString (PyExc_RuntimeError, strerror (errno));
+ PyErr_SetFromErrno (PyExc_RuntimeError);
return NULL;
}
@@ -271,7 +271,7 @@ get_all_event_callbacks (guestfs_h *g, size_t *len_rtn)
/* Copy them into the return array. */
r = malloc (sizeof (PyObject *) * (*len_rtn));
if (r == NULL) {
- PyErr_SetNone (PyExc_MemoryError);
+ PyErr_NoMemory ();
return NULL;
}
@@ -298,7 +298,7 @@ guestfs_int_py_get_string_list (PyObject *obj)
assert (obj);
if (!PyList_Check (obj)) {
- PyErr_SetString (PyExc_RuntimeError, "expecting a list parameter");
+ PyErr_SetString (PyExc_TypeError, "expecting a list parameter");
return NULL;
}
@@ -310,7 +310,7 @@ guestfs_int_py_get_string_list (PyObject *obj)
len = (size_t) slen;
r = malloc (sizeof (char *) * (len+1));
if (r == NULL) {
- PyErr_SetString (PyExc_RuntimeError, "get_string_list: out of memory");
+ PyErr_NoMemory ();
return NULL;
}
--
2.9.3
7 years, 7 months
[PATCH 1/2] daemon: lvm: use 'yes' as boolean for lvm2
by Pino Toscano
It looks like older versions of lvm2 (recent enough to have selectors)
do not recognize '1' (and '0') as boolean values. Switch to 'yes',
which seems to be supported.
Updates commit 7367945647e774aec4b93c3bf13181212d3c6430.
---
daemon/lvm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/daemon/lvm.c b/daemon/lvm.c
index a270b13..c186a5a 100644
--- a/daemon/lvm.c
+++ b/daemon/lvm.c
@@ -264,7 +264,7 @@ do_lvs (void)
r = command (&out, &err,
str_lvm, "lvs",
"-o", "vg_name,lv_name",
- "-S", "lv_role=public && lv_skip_activation!=1",
+ "-S", "lv_role=public && lv_skip_activation!=yes",
"--noheadings",
"--separator", "/", NULL);
if (r == -1) {
--
2.9.3
7 years, 7 months
[PATCH] RHBZ#1406906: check return value of Python object functions
by Matteo Cafasso
Verify the returned values of Python Object constructor functions
are not NULL before adding them to a collection.
This is particularly relevant when constructing Unicode strings in
Python 3 as they will return NULL if non UTF-8 characters are present.
Signed-off-by: Matteo Cafasso <noxdafox(a)gmail.com>
---
generator/python.ml | 102 ++++++++++++++++++++++++++---------------
python/handle.c | 34 +++++++++++---
python/t/test830RHBZ1406906.py | 51 +++++++++++++++++++++
3 files changed, 145 insertions(+), 42 deletions(-)
create mode 100644 python/t/test830RHBZ1406906.py
diff --git a/generator/python.ml b/generator/python.ml
index cf0829489..4cae24757 100644
--- a/generator/python.ml
+++ b/generator/python.ml
@@ -155,12 +155,20 @@ and generate_python_structs () =
pr "PyObject *\n";
pr "guestfs_int_py_put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
pr "{\n";
- pr " PyObject *list;\n";
+ pr " PyObject *list, *element;\n";
pr " size_t i;\n";
pr "\n";
pr " list = PyList_New (%ss->len);\n" typ;
- pr " for (i = 0; i < %ss->len; ++i)\n" typ;
- pr " PyList_SetItem (list, i, guestfs_int_py_put_%s (&%ss->val[i]));\n" typ typ;
+ pr " if (list == NULL)\n";
+ pr " return NULL;\n";
+ pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
+ pr " element = guestfs_int_py_put_%s (&%ss->val[i]);\n" typ typ;
+ pr " if (element == NULL) {\n";
+ pr " Py_CLEAR (list);\n";
+ pr " return NULL;\n";
+ pr " }\n";
+ pr " PyList_SetItem (list, i, element);\n";
+ pr " }\n";
pr " return list;\n";
pr "};\n";
pr "#endif\n";
@@ -174,54 +182,72 @@ and generate_python_structs () =
pr "PyObject *\n";
pr "guestfs_int_py_put_%s (struct guestfs_%s *%s)\n" typ typ typ;
pr "{\n";
- pr " PyObject *dict;\n";
+ pr " PyObject *dict, *value;\n";
pr "\n";
pr " dict = PyDict_New ();\n";
+ pr " if (dict == NULL)\n";
+ pr " return NULL;\n";
List.iter (
function
| name, FString ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " guestfs_int_py_fromstring (%s->%s));\n"
- typ name
+ pr " value = guestfs_int_py_fromstring (%s->%s);" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FBuffer ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " guestfs_int_py_fromstringsize (%s->%s, %s->%s_len));\n"
- typ name typ name
+ pr " value = guestfs_int_py_fromstringsize (%s->%s, %s->%s_len);\n"
+ typ name typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FUUID ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " guestfs_int_py_fromstringsize (%s->%s, 32));\n"
- typ name
+ pr " value = guestfs_int_py_fromstringsize (%s->%s, 32);\n"
+ typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, (FBytes|FUInt64) ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromUnsignedLongLong (%s->%s);\n" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FInt64 ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromLongLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromLongLong (%s->%s);\n" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FUInt32 ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromUnsignedLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromUnsignedLong (%s->%s);\n" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FInt32 ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyLong_FromLong (%s->%s));\n"
- typ name
+ pr " value = PyLong_FromLong (%s->%s);\n" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
| name, FOptPercent ->
- pr " if (%s->%s >= 0)\n" typ name;
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyFloat_FromDouble ((double) %s->%s));\n"
- typ name;
+ pr " if (%s->%s >= 0) {\n" typ name;
+ pr " value = PyFloat_FromDouble ((double) %s->%s);\n" typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
+ pr " }\n";
pr " else {\n";
pr " Py_INCREF (Py_None);\n";
pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
pr " }\n"
| name, FChar ->
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " guestfs_int_py_fromstringsize (&%s->%s, 1));\n"
- typ name
+ pr " value = guestfs_int_py_fromstringsize (&%s->%s, 1);\n"
+ typ name;
+ pr " if (value == NULL)\n";
+ pr " goto err;\n";
+ pr " PyDict_SetItemString (dict, \"%s\", value);\n" name;
) cols;
pr " return dict;\n";
+ pr " err:\n";
+ pr " Py_CLEAR (dict);\n";
+ pr " return NULL;\n";
pr "};\n";
pr "#endif\n";
pr "\n";
@@ -472,16 +498,20 @@ and generate_python_actions actions () =
pr " if (py_r == NULL) goto out;\n";
| RStringList _ ->
pr " py_r = guestfs_int_py_put_string_list (r);\n";
- pr " guestfs_int_free_string_list (r);\n"
+ pr " guestfs_int_free_string_list (r);\n";
+ pr " if (py_r == NULL) goto out;\n";
| RStruct (_, typ) ->
pr " py_r = guestfs_int_py_put_%s (r);\n" typ;
- pr " guestfs_free_%s (r);\n" typ
+ pr " guestfs_free_%s (r);\n" typ;
+ pr " if (py_r == NULL) goto out;\n";
| RStructList (_, typ) ->
pr " py_r = guestfs_int_py_put_%s_list (r);\n" typ;
- pr " guestfs_free_%s_list (r);\n" typ
+ pr " guestfs_free_%s_list (r);\n" typ;
+ pr " if (py_r == NULL) goto out;\n";
| RHashtable _ ->
pr " py_r = guestfs_int_py_put_table (r);\n";
- pr " guestfs_int_free_string_list (r);\n"
+ pr " guestfs_int_free_string_list (r);\n";
+ pr " if (py_r == NULL) goto out;\n";
| RBufferOut _ ->
pr " py_r = guestfs_int_py_fromstringsize (r, size);\n";
pr " free (r);\n";
diff --git a/python/handle.c b/python/handle.c
index 88024e184..fa6578034 100644
--- a/python/handle.c
+++ b/python/handle.c
@@ -324,15 +324,23 @@ guestfs_int_py_get_string_list (PyObject *obj)
PyObject *
guestfs_int_py_put_string_list (char * const * const argv)
{
- PyObject *list;
+ PyObject *list, *item;
size_t argc, i;
for (argc = 0; argv[argc] != NULL; ++argc)
;
list = PyList_New (argc);
+ if (list == NULL)
+ return NULL;
for (i = 0; i < argc; ++i) {
- PyList_SetItem (list, i, guestfs_int_py_fromstring (argv[i]));
+ item = guestfs_int_py_fromstring (argv[i]);
+ if (item == NULL) {
+ Py_CLEAR (list);
+ return NULL;
+ }
+
+ PyList_SetItem (list, i, item);
}
return list;
@@ -341,21 +349,35 @@ guestfs_int_py_put_string_list (char * const * const argv)
PyObject *
guestfs_int_py_put_table (char * const * const argv)
{
- PyObject *list, *item;
+ PyObject *list, *tuple, *item;
size_t argc, i;
for (argc = 0; argv[argc] != NULL; ++argc)
;
list = PyList_New (argc >> 1);
+ if (list == NULL)
+ return NULL;
for (i = 0; i < argc; i += 2) {
- item = PyTuple_New (2);
- PyTuple_SetItem (item, 0, guestfs_int_py_fromstring (argv[i]));
- PyTuple_SetItem (item, 1, guestfs_int_py_fromstring (argv[i+1]));
+ tuple = PyTuple_New (2);
+ if (tuple == NULL)
+ goto err;
+ item = guestfs_int_py_fromstring (argv[i]);
+ if (item == NULL)
+ goto err;
+ PyTuple_SetItem (tuple, 0, item);
+ item = guestfs_int_py_fromstring (argv[i+1]);
+ if (item == NULL)
+ goto err;
+ PyTuple_SetItem (tuple, 1, item);
PyList_SetItem (list, i >> 1, item);
}
return list;
+ err:
+ Py_CLEAR (list);
+ Py_CLEAR (tuple);
+ return NULL;
}
PyObject *
diff --git a/python/t/test830RHBZ1406906.py b/python/t/test830RHBZ1406906.py
new file mode 100644
index 000000000..6cef982f9
--- /dev/null
+++ b/python/t/test830RHBZ1406906.py
@@ -0,0 +1,51 @@
+# libguestfs Python bindings
+# Copyright (C) 2017 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import os
+import sys
+import shutil
+import tempfile
+import unittest
+
+import guestfs
+
+
+class Test830RHBZ1406906(unittest.TestCase):
+ def setUp(self):
+ self.tempdir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ shutil.rmtree(self.tempdir)
+
+ def test_rhbz1406906(self):
+ g = guestfs.GuestFS(python_return_dict=True)
+
+ g.add_drive_scratch(512 * 1024 * 1024)
+ g.launch()
+
+ g.part_disk("/dev/sda", "mbr")
+ g.mkfs("ext4", "/dev/sda1")
+ g.mount("/dev/sda1", "/")
+
+ # touch file with illegal unicode character
+ open(os.path.join(self.tempdir, "\udcd4"), "w").close()
+
+ g.copy_in(self.tempdir, "/")
+
+ if sys.version_info.major == 3:
+ with self.assertRaises(UnicodeDecodeError):
+ g.find("/") # segfault here on Python 3
--
2.11.0
7 years, 7 months
[PATCH v2] python: add simple wrappers for PyObject<->string functions
by Pino Toscano
The current need for #ifdef's based on the presence of
PyString_FromString makes both the OCaml code of the generator, and the
generated C code a mess to read.
Hence, add three simple wrappers to make both the OCaml, and C code more
readable, and easier to tweak in the future.
---
generator/python.ml | 72 ++++++++++++-----------------------------------------
python/handle.c | 65 ++++++++++++++++++++++++++---------------------
2 files changed, 53 insertions(+), 84 deletions(-)
diff --git a/generator/python.ml b/generator/python.ml
index 0162733..cf08294 100644
--- a/generator/python.ml
+++ b/generator/python.ml
@@ -91,6 +91,9 @@ extern PyObject *guestfs_int_py_event_to_string (PyObject *self, PyObject *args)
extern char **guestfs_int_py_get_string_list (PyObject *obj);
extern PyObject *guestfs_int_py_put_string_list (char * const * const argv);
extern PyObject *guestfs_int_py_put_table (char * const * const argv);
+extern PyObject *guestfs_int_py_fromstring (const char *str);
+extern PyObject *guestfs_int_py_fromstringsize (const char *str, size_t size);
+extern char *guestfs_int_py_asstring (PyObject *obj);
";
@@ -178,31 +181,16 @@ and generate_python_structs () =
function
| name, FString ->
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " PyString_FromString (%s->%s));\n"
- typ name;
- pr "#else\n";
- pr " PyUnicode_FromString (%s->%s));\n"
- typ name;
- pr "#endif\n"
+ pr " guestfs_int_py_fromstring (%s->%s));\n"
+ typ name
| name, FBuffer ->
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
- typ name typ name;
- pr "#else\n";
- pr " PyBytes_FromStringAndSize (%s->%s, %s->%s_len));\n"
- typ name typ name;
- pr "#endif\n"
+ pr " guestfs_int_py_fromstringsize (%s->%s, %s->%s_len));\n"
+ typ name typ name
| name, FUUID ->
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " PyString_FromStringAndSize (%s->%s, 32));\n"
- typ name;
- pr "#else\n";
- pr " PyBytes_FromStringAndSize (%s->%s, 32));\n"
- typ name;
- pr "#endif\n"
+ pr " guestfs_int_py_fromstringsize (%s->%s, 32));\n"
+ typ name
| name, (FBytes|FUInt64) ->
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
@@ -229,15 +217,9 @@ and generate_python_structs () =
pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
pr " }\n"
| name, FChar ->
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyString_FromStringAndSize (&%s->%s, 1));\n"
- typ name;
- pr "#else\n";
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyUnicode_FromStringAndSize (&%s->%s, 1));\n"
- typ name;
- pr "#endif\n"
+ pr " guestfs_int_py_fromstringsize (&%s->%s, 1));\n"
+ typ name
) cols;
pr " return dict;\n";
pr "};\n";
@@ -419,13 +401,7 @@ and generate_python_actions actions () =
pr " optargs_s.%s = PyLong_AsLongLong (py_%s);\n" n n;
pr " if (PyErr_Occurred ()) goto out;\n"
| OString _ ->
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " optargs_s.%s = PyString_AsString (py_%s);\n" n n;
- pr "#else\n";
- pr " PyObject *bytes;\n";
- pr " bytes = PyUnicode_AsUTF8String (py_%s);\n" n;
- pr " optargs_s.%s = PyBytes_AS_STRING (bytes);\n" n;
- pr "#endif\n";
+ pr " optargs_s.%s = guestfs_int_py_asstring (py_%s);\n" n n
| OStringList _ ->
pr " optargs_s.%s = guestfs_int_py_get_string_list (py_%s);\n" n n;
pr " if (!optargs_s.%s) goto out;\n" n;
@@ -480,30 +456,18 @@ and generate_python_actions actions () =
| RBool _ -> pr " py_r = PyLong_FromLong ((long) r);\n"
| RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
| RConstString _ ->
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " py_r = PyString_FromString (r);\n";
- pr "#else\n";
- pr " py_r = PyUnicode_FromString (r);\n";
- pr "#endif\n";
+ pr " py_r = guestfs_int_py_fromstring (r);\n";
pr " if (py_r == NULL) goto out;\n";
| RConstOptString _ ->
pr " if (r) {\n";
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " py_r = PyString_FromString (r);\n";
- pr "#else\n";
- pr " py_r = PyUnicode_FromString (r);\n";
- pr "#endif\n";
+ pr " py_r = guestfs_int_py_fromstring (r);\n";
pr " } else {\n";
pr " Py_INCREF (Py_None);\n";
pr " py_r = Py_None;\n";
pr " }\n";
pr " if (py_r == NULL) goto out;\n";
| RString _ ->
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " py_r = PyString_FromString (r);\n";
- pr "#else\n";
- pr " py_r = PyUnicode_FromString (r);\n";
- pr "#endif\n";
+ pr " py_r = guestfs_int_py_fromstring (r);\n";
pr " free (r);\n";
pr " if (py_r == NULL) goto out;\n";
| RStringList _ ->
@@ -519,11 +483,7 @@ and generate_python_actions actions () =
pr " py_r = guestfs_int_py_put_table (r);\n";
pr " guestfs_int_free_string_list (r);\n"
| RBufferOut _ ->
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " py_r = PyString_FromStringAndSize (r, size);\n";
- pr "#else\n";
- pr " py_r = PyBytes_FromStringAndSize (r, size);\n";
- pr "#endif\n";
+ pr " py_r = guestfs_int_py_fromstringsize (r, size);\n";
pr " free (r);\n";
pr " if (py_r == NULL) goto out;\n";
);
diff --git a/python/handle.c b/python/handle.c
index 806408f..f347c00 100644
--- a/python/handle.c
+++ b/python/handle.c
@@ -241,11 +241,7 @@ guestfs_int_py_event_to_string (PyObject *self, PyObject *args)
return NULL;
}
-#ifdef HAVE_PYSTRING_ASSTRING
- py_r = PyString_FromString (str);
-#else
- py_r = PyUnicode_FromString (str);
-#endif
+ py_r = guestfs_int_py_fromstring (str);
free (str);
return py_r;
@@ -298,9 +294,6 @@ guestfs_int_py_get_string_list (PyObject *obj)
{
size_t i, len;
char **r;
-#ifndef HAVE_PYSTRING_ASSTRING
- PyObject *bytes;
-#endif
assert (obj);
@@ -321,14 +314,8 @@ guestfs_int_py_get_string_list (PyObject *obj)
return NULL;
}
- for (i = 0; i < len; ++i) {
-#ifdef HAVE_PYSTRING_ASSTRING
- r[i] = PyString_AsString (PyList_GetItem (obj, i));
-#else
- bytes = PyUnicode_AsUTF8String (PyList_GetItem (obj, i));
- r[i] = PyBytes_AS_STRING (bytes);
-#endif
- }
+ for (i = 0; i < len; ++i)
+ r[i] = guestfs_int_py_asstring (PyList_GetItem (obj, i));
r[len] = NULL;
return r;
@@ -345,11 +332,7 @@ guestfs_int_py_put_string_list (char * const * const argv)
list = PyList_New (argc);
for (i = 0; i < argc; ++i) {
-#ifdef HAVE_PYSTRING_ASSTRING
- PyList_SetItem (list, i, PyString_FromString (argv[i]));
-#else
- PyList_SetItem (list, i, PyUnicode_FromString (argv[i]));
-#endif
+ PyList_SetItem (list, i, guestfs_int_py_fromstring (argv[i]));
}
return list;
@@ -367,15 +350,41 @@ guestfs_int_py_put_table (char * const * const argv)
list = PyList_New (argc >> 1);
for (i = 0; i < argc; i += 2) {
item = PyTuple_New (2);
-#ifdef HAVE_PYSTRING_ASSTRING
- PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
- PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
-#else
- PyTuple_SetItem (item, 0, PyUnicode_FromString (argv[i]));
- PyTuple_SetItem (item, 1, PyUnicode_FromString (argv[i+1]));
-#endif
+ PyTuple_SetItem (item, 0, guestfs_int_py_fromstring (argv[i]));
+ PyTuple_SetItem (item, 1, guestfs_int_py_fromstring (argv[i+1]));
PyList_SetItem (list, i >> 1, item);
}
return list;
}
+
+PyObject *
+guestfs_int_py_fromstring (const char *str)
+{
+#ifdef HAVE_PYSTRING_ASSTRING
+ return PyString_FromString (str);
+#else
+ return PyUnicode_FromString (str);
+#endif
+}
+
+PyObject *
+guestfs_int_py_fromstringsize (const char *str, size_t size)
+{
+#ifdef HAVE_PYSTRING_ASSTRING
+ return PyString_FromStringAndSize (str, size);
+#else
+ return PyString_FromStringAndSize (str, size);
+#endif
+}
+
+char *
+guestfs_int_py_asstring (PyObject *obj)
+{
+#ifdef HAVE_PYSTRING_ASSTRING
+ return PyString_AsString (obj);
+#else
+ PyObject *bytes = PyUnicode_AsUTF8String (obj);
+ return PyBytes_AS_STRING (bytes);
+#endif
+}
--
2.9.3
7 years, 7 months
[Bug 1406906] [PATCH 0/3] Fix segmentation fault in Python bindings
by Matteo Cafasso
This series addresses the issue where non UTF8 file names in a guest image lead to libguestfs segfault with Python 3 APIs.
The core issue is the APIs are not checking the return value when constructing a new PyObject. Therefore NULL pointers are added to Python collections (lists and dictionaries) crashing the application.
Few notes regarding the comments on the previous patch.
- Added a regression test file
- Removed the Exception string setter functions as Python APIs already set them in case of error
https://docs.python.org/3.6/c-api/exceptions.html#exception-handling (third paragraph)
- Fixed functions in python/handle.c
- Correctly clear and decrement the refcount of the list/dictionary object before returning on error
Matteo Cafasso (3):
generator: check return value of Python object functions
python: check return value of object functions in handle.c
python: add regression test for RHBZ#1406906
generator/python.ml | 119 +++++++++++++++++++++++++----------------
python/handle.c | 48 +++++++++++++----
python/t/test830RHBZ1406906.py | 55 +++++++++++++++++++
3 files changed, 165 insertions(+), 57 deletions(-)
create mode 100644 python/t/test830RHBZ1406906.py
--
2.11.0
7 years, 7 months
[PATCH] python: add simple wrappers for PyObject<->string functions
by Pino Toscano
The current need for #ifdef's based on the presence of
PyString_FromString makes both the OCaml code of the generator, and the
generated C code a mess to read.
Hence, add three simple wrappers to make both the OCaml, and C code more
readable, and easier to tweak in the future.
---
generator/python.ml | 72 ++++++++++++-----------------------------------------
python/handle.c | 52 +++++++++++++++++++++++++-------------
2 files changed, 51 insertions(+), 73 deletions(-)
diff --git a/generator/python.ml b/generator/python.ml
index 0162733..cf08294 100644
--- a/generator/python.ml
+++ b/generator/python.ml
@@ -91,6 +91,9 @@ extern PyObject *guestfs_int_py_event_to_string (PyObject *self, PyObject *args)
extern char **guestfs_int_py_get_string_list (PyObject *obj);
extern PyObject *guestfs_int_py_put_string_list (char * const * const argv);
extern PyObject *guestfs_int_py_put_table (char * const * const argv);
+extern PyObject *guestfs_int_py_fromstring (const char *str);
+extern PyObject *guestfs_int_py_fromstringsize (const char *str, size_t size);
+extern char *guestfs_int_py_asstring (PyObject *obj);
";
@@ -178,31 +181,16 @@ and generate_python_structs () =
function
| name, FString ->
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " PyString_FromString (%s->%s));\n"
- typ name;
- pr "#else\n";
- pr " PyUnicode_FromString (%s->%s));\n"
- typ name;
- pr "#endif\n"
+ pr " guestfs_int_py_fromstring (%s->%s));\n"
+ typ name
| name, FBuffer ->
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
- typ name typ name;
- pr "#else\n";
- pr " PyBytes_FromStringAndSize (%s->%s, %s->%s_len));\n"
- typ name typ name;
- pr "#endif\n"
+ pr " guestfs_int_py_fromstringsize (%s->%s, %s->%s_len));\n"
+ typ name typ name
| name, FUUID ->
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " PyString_FromStringAndSize (%s->%s, 32));\n"
- typ name;
- pr "#else\n";
- pr " PyBytes_FromStringAndSize (%s->%s, 32));\n"
- typ name;
- pr "#endif\n"
+ pr " guestfs_int_py_fromstringsize (%s->%s, 32));\n"
+ typ name
| name, (FBytes|FUInt64) ->
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
@@ -229,15 +217,9 @@ and generate_python_structs () =
pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
pr " }\n"
| name, FChar ->
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyString_FromStringAndSize (&%s->%s, 1));\n"
- typ name;
- pr "#else\n";
- pr " PyDict_SetItemString (dict, \"%s\",\n" name;
- pr " PyUnicode_FromStringAndSize (&%s->%s, 1));\n"
- typ name;
- pr "#endif\n"
+ pr " guestfs_int_py_fromstringsize (&%s->%s, 1));\n"
+ typ name
) cols;
pr " return dict;\n";
pr "};\n";
@@ -419,13 +401,7 @@ and generate_python_actions actions () =
pr " optargs_s.%s = PyLong_AsLongLong (py_%s);\n" n n;
pr " if (PyErr_Occurred ()) goto out;\n"
| OString _ ->
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " optargs_s.%s = PyString_AsString (py_%s);\n" n n;
- pr "#else\n";
- pr " PyObject *bytes;\n";
- pr " bytes = PyUnicode_AsUTF8String (py_%s);\n" n;
- pr " optargs_s.%s = PyBytes_AS_STRING (bytes);\n" n;
- pr "#endif\n";
+ pr " optargs_s.%s = guestfs_int_py_asstring (py_%s);\n" n n
| OStringList _ ->
pr " optargs_s.%s = guestfs_int_py_get_string_list (py_%s);\n" n n;
pr " if (!optargs_s.%s) goto out;\n" n;
@@ -480,30 +456,18 @@ and generate_python_actions actions () =
| RBool _ -> pr " py_r = PyLong_FromLong ((long) r);\n"
| RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
| RConstString _ ->
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " py_r = PyString_FromString (r);\n";
- pr "#else\n";
- pr " py_r = PyUnicode_FromString (r);\n";
- pr "#endif\n";
+ pr " py_r = guestfs_int_py_fromstring (r);\n";
pr " if (py_r == NULL) goto out;\n";
| RConstOptString _ ->
pr " if (r) {\n";
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " py_r = PyString_FromString (r);\n";
- pr "#else\n";
- pr " py_r = PyUnicode_FromString (r);\n";
- pr "#endif\n";
+ pr " py_r = guestfs_int_py_fromstring (r);\n";
pr " } else {\n";
pr " Py_INCREF (Py_None);\n";
pr " py_r = Py_None;\n";
pr " }\n";
pr " if (py_r == NULL) goto out;\n";
| RString _ ->
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " py_r = PyString_FromString (r);\n";
- pr "#else\n";
- pr " py_r = PyUnicode_FromString (r);\n";
- pr "#endif\n";
+ pr " py_r = guestfs_int_py_fromstring (r);\n";
pr " free (r);\n";
pr " if (py_r == NULL) goto out;\n";
| RStringList _ ->
@@ -519,11 +483,7 @@ and generate_python_actions actions () =
pr " py_r = guestfs_int_py_put_table (r);\n";
pr " guestfs_int_free_string_list (r);\n"
| RBufferOut _ ->
- pr "#ifdef HAVE_PYSTRING_ASSTRING\n";
- pr " py_r = PyString_FromStringAndSize (r, size);\n";
- pr "#else\n";
- pr " py_r = PyBytes_FromStringAndSize (r, size);\n";
- pr "#endif\n";
+ pr " py_r = guestfs_int_py_fromstringsize (r, size);\n";
pr " free (r);\n";
pr " if (py_r == NULL) goto out;\n";
);
diff --git a/python/handle.c b/python/handle.c
index 806408f..1840f91 100644
--- a/python/handle.c
+++ b/python/handle.c
@@ -241,11 +241,7 @@ guestfs_int_py_event_to_string (PyObject *self, PyObject *args)
return NULL;
}
-#ifdef HAVE_PYSTRING_ASSTRING
- py_r = PyString_FromString (str);
-#else
- py_r = PyUnicode_FromString (str);
-#endif
+ py_r = guestfs_int_py_fromstring (str);
free (str);
return py_r;
@@ -345,11 +341,7 @@ guestfs_int_py_put_string_list (char * const * const argv)
list = PyList_New (argc);
for (i = 0; i < argc; ++i) {
-#ifdef HAVE_PYSTRING_ASSTRING
- PyList_SetItem (list, i, PyString_FromString (argv[i]));
-#else
- PyList_SetItem (list, i, PyUnicode_FromString (argv[i]));
-#endif
+ PyList_SetItem (list, i, guestfs_int_py_fromstring (argv[i]));
}
return list;
@@ -367,15 +359,41 @@ guestfs_int_py_put_table (char * const * const argv)
list = PyList_New (argc >> 1);
for (i = 0; i < argc; i += 2) {
item = PyTuple_New (2);
-#ifdef HAVE_PYSTRING_ASSTRING
- PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
- PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
-#else
- PyTuple_SetItem (item, 0, PyUnicode_FromString (argv[i]));
- PyTuple_SetItem (item, 1, PyUnicode_FromString (argv[i+1]));
-#endif
+ PyTuple_SetItem (item, 0, guestfs_int_py_fromstring (argv[i]));
+ PyTuple_SetItem (item, 1, guestfs_int_py_fromstring (argv[i+1]));
PyList_SetItem (list, i >> 1, item);
}
return list;
}
+
+PyObject *
+guestfs_int_py_fromstring (const char *str)
+{
+#ifdef HAVE_PYSTRING_ASSTRING
+ return PyString_FromString (str);
+#else
+ return PyUnicode_FromString (str);
+#endif
+}
+
+PyObject *
+guestfs_int_py_fromstringsize (const char *str, size_t size)
+{
+#ifdef HAVE_PYSTRING_ASSTRING
+ return PyString_FromStringAndSize (str, size);
+#else
+ return PyString_FromStringAndSize (str, size);
+#endif
+}
+
+char *
+guestfs_int_py_asstring (PyObject *obj)
+{
+#ifdef HAVE_PYSTRING_ASSTRING
+ return PyString_AsString (obj);
+#else
+ PyObject *bytes = PyUnicode_AsUTF8String (obj);
+ return PyBytes_AS_STRING (bytes);
+#endif
+}
--
2.9.3
7 years, 7 months