Package: gawk
Version: 3.1.5.dfsg-4
Tags: patch
First reported to Ubuntu at
https://bugs.launchpad.net/ubuntu/+source/gawk/+bug/58256
Details may be seen there.
Problem has been fixed upstream in CVS; I've attached a debdiff against
which backports the relevant source changes.
With the text file below (rc_cmp.txt) in the working directory, the
following command produces an error
$ cat rc_cmp.txt | gawk '{length($1)}'
*** glibc detected *** double free or corruption (fasttop): 0x080ae700 ***
Aborted
rc_cmp.txt:
## List of components contained in system rc
## File rc_cmp.txt
## Created by mtt on Wed Aug 30 21:09:19 BST 2006
0
1
C:c
R:r
SS:e1
SS:e2
diff -u gawk-3.1.5.dfsg/debian/patches/00list
gawk-3.1.5.dfsg/debian/patches/00list
--- gawk-3.1.5.dfsg/debian/patches/00list
+++ gawk-3.1.5.dfsg/debian/patches/00list
@@ -4,0 +5 @@
+25_free_wstr-and-multiple-frees
diff -u gawk-3.1.5.dfsg/debian/changelog gawk-3.1.5.dfsg/debian/changelog
--- gawk-3.1.5.dfsg/debian/changelog
+++ gawk-3.1.5.dfsg/debian/changelog
@@ -1,3 +1,11 @@
+gawk (1:3.1.5.dfsg-5) unstable; urgency=low
+
+ * 25_free_wstr-and-multiple-frees.dpatch: brought in some changes from
+ current CVS, to resolve an issue with multiple frees (closes Malone
+ bug #58256).
+
+ -- Micah Cowan <[EMAIL PROTECTED]> Fri, 6 Apr 2007 11:33:50 -0700
+
gawk (1:3.1.5.dfsg-4) unstable; urgency=low
* doc/gawk.info, doc/gawk.texi, doc/gawkinet.info, doc/gawkinet.texi:
only in patch2:
unchanged:
--- gawk-3.1.5.dfsg.orig/debian/patches/25_free_wstr-and-multiple-frees.dpatch
+++ gawk-3.1.5.dfsg/debian/patches/25_free_wstr-and-multiple-frees.dpatch
@@ -0,0 +1,182 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 25_free_wstr-and-multiple-frees.dpatch by <[EMAIL PROTECTED]>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Brought in from CVS, 6 Apr 2007. This patch was brought in
+## DP: specifically to address an issue with multiple free()s in
+## DP: str2wstr().
+
[EMAIL PROTECTED]@
+diff -urNad gawk-3.1.5.dfsg~/awk.h gawk-3.1.5.dfsg/awk.h
+--- gawk-3.1.5.dfsg~/awk.h 2005-07-26 11:07:43.000000000 -0700
++++ gawk-3.1.5.dfsg/awk.h 2007-04-06 12:17:09.000000000 -0700
+@@ -1166,6 +1166,9 @@
+ #define force_wstring(n) str2wstr(n, NULL)
+ extern const wchar_t *wstrstr P((const wchar_t *haystack, size_t hs_len,
const wchar_t *needle, size_t needle_len));
+ extern const wchar_t *wcasestrstr P((const wchar_t *haystack, size_t hs_len,
const wchar_t *needle, size_t needle_len));
++extern void free_wstr P((NODE *n));
++#else
++#define free_wstr(NODE) /* empty */
+ #endif
+ /* re.c */
+ extern Regexp *make_regexp P((const char *s, size_t len, int ignorecase, int
dfa));
+diff -urNad gawk-3.1.5.dfsg~/builtin.c gawk-3.1.5.dfsg/builtin.c
+--- gawk-3.1.5.dfsg~/builtin.c 2005-07-26 11:07:43.000000000 -0700
++++ gawk-3.1.5.dfsg/builtin.c 2007-04-06 12:17:09.000000000 -0700
+@@ -2462,6 +2462,8 @@
+ free(t->stptr);
+ t->stptr = buf;
+ t->stlen = textlen;
++ free_wstr(t);
++ t->flags &= ~(NUMCUR|NUMBER);
+
+ free_temp(s);
+ if (matches > 0 && lhs) {
+@@ -2471,7 +2473,6 @@
+ }
+ if (after_assign != NULL)
+ (*after_assign)();
+- t->flags &= ~(NUMCUR|NUMBER);
+ }
+ if (mb_indices != NULL)
+ free(mb_indices);
+diff -urNad gawk-3.1.5.dfsg~/eval.c gawk-3.1.5.dfsg/eval.c
+--- gawk-3.1.5.dfsg~/eval.c 2007-04-06 12:17:09.000000000 -0700
++++ gawk-3.1.5.dfsg/eval.c 2007-04-06 12:19:52.000000000 -0700
+@@ -1176,13 +1176,7 @@
+ memcpy(l->stptr + l->stlen, r->stptr, r->stlen);
+ l->stlen += r->stlen;
+ l->stptr[l->stlen] = '\0';
+-#if defined MBS_SUPPORT
+- if (l->wstptr != NULL)
+- free(l->wstptr);
+- l->wstptr = NULL;
+- l->wstlen = 0;
+- l->flags &= ~WSTRCUR;
+-#endif /* MBS_SUPPORT */
++ free_wstr(l);
+ } else {
+ char *nval;
+ size_t nlen = l->stlen + r->stlen + 2;
+diff -urNad gawk-3.1.5.dfsg~/field.c gawk-3.1.5.dfsg/field.c
+--- gawk-3.1.5.dfsg~/field.c 2005-05-11 08:28:15.000000000 -0700
++++ gawk-3.1.5.dfsg/field.c 2007-04-06 12:17:09.000000000 -0700
+@@ -166,6 +166,7 @@
+ cops = ops;
+ ops[0] = '\0';
+ for (i = 1; i <= NF; i++) {
++ free_wstr(fields_arr[i]);
+ tmp = fields_arr[i];
+ /* copy field */
+ if (tmp->stlen == 1)
+diff -urNad gawk-3.1.5.dfsg~/node.c gawk-3.1.5.dfsg/node.c
+--- gawk-3.1.5.dfsg~/node.c 2005-07-26 11:07:43.000000000 -0700
++++ gawk-3.1.5.dfsg/node.c 2007-04-06 12:17:09.000000000 -0700
+@@ -216,15 +216,7 @@
+ no_malloc:
+ s->stref = 1;
+ s->flags |= STRCUR;
+-#if defined MBS_SUPPORT
+- if ((s->flags & WSTRCUR) != 0) {
+- assert(s->wstptr != NULL);
+- free(s->wstptr);
+- s->wstptr = NULL;
+- s->wstlen = 0;
+- s->flags &= ~WSTRCUR;
+- }
+-#endif
++ free_wstr(s);
+ return s;
+ }
+
+@@ -288,7 +280,13 @@
+ r->flags &= ~(PERM|TEMP|FIELD);
+ r->flags |= MALLOC;
+ #if defined MBS_SUPPORT
++ /*
++ * DON'T call free_wstr(r) here!
++ * r->wstptr still points at n->wstptr's value, and we
++ * don't want to free it!
++ */
+ r->wstptr = NULL;
++ r->wstlen = 0;
+ #endif /* defined MBS_SUPPORT */
+ if (n->type == Node_val && (n->flags & STRCUR) != 0) {
+ r->stref = 1;
+@@ -344,11 +342,7 @@
+ r->stref = 1;
+ r->stptr = NULL;
+ r->stlen = 0;
+-#if defined MBS_SUPPORT
+- r->wstptr = NULL;
+- r->wstlen = 0;
+- r->flags &= ~WSTRCUR;
+-#endif /* MBS_SUPPORT */
++ free_wstr(r);
+ #endif /* GAWKDEBUG */
+ return r;
+ }
+@@ -510,20 +504,13 @@
+ return;
+ }
+ free(tmp->stptr);
+-#if defined MBS_SUPPORT
+- if (tmp->wstptr != NULL) {
+- assert((tmp->flags & WSTRCUR) != 0);
+- free(tmp->wstptr);
+- }
+- tmp->flags &= ~WSTRCUR;
+- tmp->wstptr = NULL;
+- tmp->wstlen = 0;
+-#endif
++ free_wstr(tmp);
+ }
+ freenode(tmp);
+ return;
+ }
+ if ((tmp->flags & FIELD) != 0) {
++ free_wstr(tmp);
+ freenode(tmp);
+ return;
+ }
+@@ -702,16 +689,11 @@
+ if ((n->flags & WSTRCUR) != 0) {
+ if (ptr == NULL)
+ return n;
++ free_wstr(n);
+ /* otherwise
+ fall through and recompute to fill in the array */
+ }
+
+- if (n->wstptr != NULL) {
+- free(n->wstptr);
+- n->wstptr = NULL;
+- n->wstlen = 0;
+- }
+-
+ /*
+ * After consideration and consultation, this
+ * code trades space for time. We allocate
+@@ -775,6 +757,22 @@
+ return n;
+ }
+
++/* free_wstr --- release the wide string part of a node */
++
++void
++free_wstr(NODE *n)
++{
++ assert(n->type == Node_val);
++
++ if ((n->flags & WSTRCUR) != 0) {
++ assert(n->wstptr != NULL);
++ free(n->wstptr);
++ }
++ n->wstptr = NULL;
++ n->wstlen = 0;
++ n->flags &= ~WSTRCUR;
++}
++
+ #if 0
+ static void
+ dump_wstr(FILE *fp, const wchar_t *str, size_t len)