Peter Wu
2014-Aug-08 09:31 UTC
[Libguestfs] [PATCH 0/2] Fix (minor) bugs found by Clang static analyzer
Hi, Here are more fixes for bugs caught my Clang static analyzer. Two bugs are remaining, namely a memleak in the perl bindings. I am not an expert in that area and did not manage to fix it in a correct way, so I will just describe it. The ASetValues and ASetValue functions call a function which allocates memory. The generated code puts this before PREINIT. Then there is the typemap for hive_h object. This code can return if the validation fails which causes a memleak. So, could some Perl programmer pick this up? Peter Wu (2): Silence dead assigmnents/initialization/increments Avoid calling calloc(0, x) lib/write.c | 12 +++++------- sh/hivexsh.c | 4 ++++ 2 files changed, 9 insertions(+), 7 deletions(-) -- 2.0.2 PS. now I'll have a look at the Python bug wrt set_value.
Peter Wu
2014-Aug-08 09:31 UTC
[Libguestfs] [PATCH 1/2] Silence dead assigmnents/initialization/increments
Some of these assignments were introduced in commit
c9d5cd059c45fd3aa6d16b3ba185d7cb3a08de9e ("hivex: Fix allocations that
may move C heap buffer."), but turn out to be unnecessary (unused).
Replace the assignments by a comment in case someone extends the code
later.
Caught by Clang static analyzer.
---
lib/write.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/lib/write.c b/lib/write.c
index 9de8ecd..abd12c5 100644
--- a/lib/write.c
+++ b/lib/write.c
@@ -264,7 +264,6 @@ delete_values (hive_h *h, hive_node_h node)
int is_inline;
len = le32toh (vk->data_len);
is_inline = !!(len & 0x80000000); /* top bit indicates is inline */
- len &= 0x7fffffff;
if (!is_inline) { /* non-inline, so remove data block */
size_t data_offset = le32toh (vk->data_offset);
@@ -707,7 +706,7 @@ hivex_node_add_child (hive_h *h, hive_node_h parent, const
char *name)
/* Recalculate pointers that could have been invalidated by
* previous call to allocate_block (via new_lh_record).
*/
- nk = (struct ntreg_nk_record *) ((char *) h->addr + nkoffset);
+ /* nk could be invalid here */
parent_nk = (struct ntreg_nk_record *) ((char *) h->addr + parent);
DEBUG (2, "no keys, allocated new lh-record at 0x%zx", lh_offs);
@@ -723,7 +722,7 @@ hivex_node_add_child (hive_h *h, hive_node_h parent, const
char *name)
/* Recalculate pointers that could have been invalidated by
* previous call to allocate_block (via new_lh_record).
*/
- nk = (struct ntreg_nk_record *) ((char *) h->addr + nkoffset);
+ /* nk could be invalid here */
parent_nk = (struct ntreg_nk_record *) ((char *) h->addr + parent);
}
@@ -950,8 +949,6 @@ hivex_node_set_values (hive_h *h, hive_node_h node,
nk->nr_values = htole32 (nr_values);
nk->vallist = htole32 (vallist_offs - 0x1000);
- struct ntreg_value_list *vallist - (struct ntreg_value_list *) ((char *)
h->addr + vallist_offs);
size_t i;
for (i = 0; i < nr_values; ++i) {
@@ -970,7 +967,8 @@ hivex_node_set_values (hive_h *h, hive_node_h node,
* previous call to allocate_block.
*/
nk = (struct ntreg_nk_record *) ((char *) h->addr + node);
- vallist = (struct ntreg_value_list *) ((char *) h->addr + vallist_offs);
+ struct ntreg_value_list *vallist + (struct ntreg_value_list *) ((char
*) h->addr + vallist_offs);
vallist->offset[i] = htole32 (vk_offs - 0x1000);
@@ -1000,7 +998,7 @@ hivex_node_set_values (hive_h *h, hive_node_h node,
* previous call to allocate_block.
*/
nk = (struct ntreg_nk_record *) ((char *) h->addr + node);
- vallist = (struct ntreg_value_list *) ((char *) h->addr +
vallist_offs);
+ /* vallist could be invalid here */
vk = (struct ntreg_vk_record *) ((char *) h->addr + vk_offs);
memcpy ((char *) h->addr + offs + 4, values[i].value, values[i].len);
--
2.0.2
The return value for zero-size allocations is implementation-defined
(can be NULL or a unique pointer for free()). Just return early here as
there is nothing to print.
Caught by Clang static analyzer.
---
sh/hivexsh.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/sh/hivexsh.c b/sh/hivexsh.c
index f578ccc..243682c 100644
--- a/sh/hivexsh.c
+++ b/sh/hivexsh.c
@@ -622,6 +622,10 @@ cmd_ls (char *args)
for (len = 0; children[len] != 0; ++len)
;
+ /* No children, no need to print anything. */
+ if (len == 0)
+ return 0;
+
char **names = calloc (len, sizeof (char *));
if (names == NULL) {
perror ("malloc");
--
2.0.2
Richard W.M. Jones
2014-Aug-08 10:27 UTC
Re: [Libguestfs] [PATCH 0/2] Fix (minor) bugs found by Clang static analyzer
On Fri, Aug 08, 2014 at 11:31:07AM +0200, Peter Wu wrote:> Hi, > > Here are more fixes for bugs caught my Clang static analyzer. Two > bugs are remaining, namely a memleak in the perl bindings. I am not > an expert in that area and did not manage to fix it in a correct > way, so I will just describe it.Thanks - pushed both.> The ASetValues and ASetValue functions call a function which > allocates memory. The generated code puts this before PREINIT. Then > there is the typemap for hive_h object. This code can return if the > validation fails which causes a memleak. > > So, could some Perl programmer pick this up?I'm not super-worried by this as: - It's only a memory leak. - It doesn't seem to be exploitable. - It can be avoided easily by not passing a bogus handle in Perl methods. - Fixing it is complex and is most likely to introduce real bugs. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org