From b64685d06f8db1aff292ec409abe25f8a483d775 Mon Sep 17 00:00:00 2001
From: John Darrington <john@darrington.wattle.id.au>
Date: Wed, 31 May 2006 07:38:03 +0000
Subject: [PATCH] Fixed minor memory leak. Character set  conversion in  value
 label dialog box. Made more robust in the presence of bad alignment and
 measure parameters.

---
 src/data/format.c              | 17 +++++++++++++++++
 src/data/format.h              |  8 ++++++--
 src/data/sys-file-reader.c     | 10 ++++++++++
 src/libpspp/i18n.c             | 15 +++++++++++----
 src/ui/gui/menu-actions.c      |  2 ++
 src/ui/gui/psppire-var-store.c | 17 ++++++++++++-----
 src/ui/gui/val-labs-dialog.c   | 15 +++++++++++----
 src/ui/gui/var-sheet.c         |  4 ++--
 src/ui/gui/var-sheet.h         |  7 +++++--
 9 files changed, 76 insertions(+), 19 deletions(-)

diff --git a/src/data/format.c b/src/data/format.c
index 5b9b7656..7066c053 100644
--- a/src/data/format.c
+++ b/src/data/format.c
@@ -372,3 +372,20 @@ make_output_format (int type, int w, int d)
   assert (check_output_specifier (&f, 0));
   return f;
 }
+
+
+bool 
+measure_is_valid(enum measure m)
+{
+  if ( m <= 0 ) return false;
+  if ( m >= n_MEASURES) false;
+  return true;
+}
+
+bool 
+alignment_is_valid(enum alignment a)
+{
+  if ( a < 0 ) return false;
+  if ( a >= n_ALIGN) return false;
+  return true;
+}
diff --git a/src/data/format.h b/src/data/format.h
index 9a717912..10ae543e 100644
--- a/src/data/format.h
+++ b/src/data/format.h
@@ -76,7 +76,8 @@ enum alignment
   {
     ALIGN_LEFT = 0,
     ALIGN_RIGHT = 1,
-    ALIGN_CENTRE = 2
+    ALIGN_CENTRE = 2, 
+    n_ALIGN
   };
 
 
@@ -84,9 +85,12 @@ enum measure
   {
     MEASURE_NOMINAL=1,
     MEASURE_ORDINAL=2,
-    MEASURE_SCALE=3
+    MEASURE_SCALE=3,
+    n_MEASURES
   };
 
+bool measure_is_valid(enum measure m);
+bool alignment_is_valid(enum alignment a);
 
 
 /* Descriptions of all the display formats above. */
diff --git a/src/data/sys-file-reader.c b/src/data/sys-file-reader.c
index 89a236d5..b5fa6212 100644
--- a/src/data/sys-file-reader.c
+++ b/src/data/sys-file-reader.c
@@ -510,6 +510,16 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
 
 		      assertive_buf_read (r, &params, sizeof(params), 0);
 
+		      if ( ! measure_is_valid(params.measure) 
+			   || 
+			   ! alignment_is_valid(params.align))
+			{
+			  msg(MW, 
+			      _("Invalid variable display parameters.  Default parameters substituted."), 
+			      fh_get_file_name(r->fh));
+			  continue;
+			}
+
 		      v = dict_get_var(*dict, i);
 
 		      v->measure = params.measure;
diff --git a/src/libpspp/i18n.c b/src/libpspp/i18n.c
index bcac52cf..360c9abd 100644
--- a/src/libpspp/i18n.c
+++ b/src/libpspp/i18n.c
@@ -54,6 +54,9 @@ recode_string(enum conv_id how,  const char *text, int length)
   /* FIXME: Need to ensure that this char is valid in the target encoding */
   const char fallbackchar = '?';
 
+  if ( text == NULL ) 
+    return NULL;
+
   if ( length == -1 ) 
      length = strlen(text);
 
@@ -71,8 +74,6 @@ recode_string(enum conv_id how,  const char *text, int length)
   inbytes = length;
   
   do {
-
-  
     result = iconv(convertor[how], &ip, &inbytes, 
 		   &op, &outbytes);
 
@@ -108,11 +109,17 @@ recode_string(enum conv_id how,  const char *text, int length)
 	  }
 
       }
-
   } while ( -1 == result );
 
+  if (outbytes == 0 ) 
+    {
+      char *const oldaddr = outbuf;
+      outbuf = xrealloc(outbuf, outbufferlength + 1);
+      
+      op += (outbuf - oldaddr) ;
+    }
+
   *op = '\0';
-  
 
   return outbuf;
 }
diff --git a/src/ui/gui/menu-actions.c b/src/ui/gui/menu-actions.c
index f031ea70..c23beb49 100644
--- a/src/ui/gui/menu-actions.c
+++ b/src/ui/gui/menu-actions.c
@@ -71,6 +71,8 @@ psppire_set_window_title(const gchar *text)
   gchar *title = g_strdup_printf("%s --- %s", text, gettext(window_title));
 
   gtk_window_set_title(GTK_WINDOW(data_editor), title);
+
+  g_free(title);
 }
 
 
diff --git a/src/ui/gui/psppire-var-store.c b/src/ui/gui/psppire-var-store.c
index 9abf8653..4cdc2958 100644
--- a/src/ui/gui/psppire-var-store.c
+++ b/src/ui/gui/psppire-var-store.c
@@ -617,14 +617,21 @@ text_for_column(const struct PsppireVariable *pv, gint c, GError **err)
       }
       break;
     case COL_ALIGN:
-      return g_locale_to_utf8(gettext(alignments[psppire_variable_get_alignment(pv)]), 
-					 -1, -0, 0, err);
+      {
+	const gint align = psppire_variable_get_alignment(pv);
+
+	g_assert(align < n_ALIGNMENTS);
+	return g_locale_to_utf8(gettext(alignments[align]),-1, -0, 0, err);
+      }
       break;
     case COL_MEASURE:
-      return g_locale_to_utf8(gettext(measures[psppire_variable_get_measure(pv)]), 
-					 -1, -0, 0, err);
-      break;
+      {
+	const gint measure = psppire_variable_get_measure(pv);
 
+	g_assert(measure < n_MEASURES);
+	return g_locale_to_utf8(gettext(measures[measure]), -1, -0, 0, err);
+      }
+      break;
     }
   return 0;
 }
diff --git a/src/ui/gui/val-labs-dialog.c b/src/ui/gui/val-labs-dialog.c
index c8be70b9..a17d8e10 100644
--- a/src/ui/gui/val-labs-dialog.c
+++ b/src/ui/gui/val-labs-dialog.c
@@ -271,6 +271,7 @@ static void
 on_select_row                  (GtkTreeView *treeview,
 				gpointer data)
 {
+  gchar *labeltext;
   struct val_labs_dialog *dialog = data;
 
   struct val_lab * vl  = get_selected_tuple(dialog);
@@ -290,8 +291,10 @@ on_select_row                  (GtkTreeView *treeview,
   g_signal_handler_block(GTK_ENTRY(dialog->label_entry), 
 			 dialog->change_handler_id);
 
+  labeltext = pspp_locale_to_utf8(vl->label, -1, 0);
   gtk_entry_set_text(GTK_ENTRY(dialog->label_entry),
-		     vl->label);
+		     labeltext);
+  g_free(labeltext);
 
   g_signal_handler_unblock(GTK_ENTRY(dialog->label_entry), 
 			 dialog->change_handler_id);
@@ -412,21 +415,25 @@ repopulate_dialog(struct val_labs_dialog *dialog)
       vl;
       vl = val_labs_next(dialog->labs, &vli))
     {
+
       gchar *const vstr  = 
 	value_to_text(vl->value, 
 		      *psppire_variable_get_write_spec(dialog->pv));
 
+      gchar *labeltext = 
+	pspp_locale_to_utf8(vl->label, -1, 0);	
 					   
-      
       gchar *const text = g_strdup_printf("%s = \"%s\"",
-					  vstr, vl->label);
- 
+					  vstr, labeltext);
+
+      
       gtk_list_store_append (list_store, &iter);
       gtk_list_store_set (list_store, &iter,
                           0, text, 
 			  1, vl->value.f,
 			  -1);
 
+      g_free(labeltext);
       g_free(text); 
       g_free(vstr);
     }
diff --git a/src/ui/gui/var-sheet.c b/src/ui/gui/var-sheet.c
index 3fd426ef..5dcbf2f6 100644
--- a/src/ui/gui/var-sheet.c
+++ b/src/ui/gui/var-sheet.c
@@ -98,14 +98,14 @@ click2row(GtkWidget *w, gint row, gpointer data)
 
 
 
-const gchar *alignments[]={
+const gchar *alignments[n_ALIGNMENTS + 1]={
   N_("Left"),
   N_("Right"),
   N_("Centre"),
   0
 };
 
-const gchar *measures[]={
+const gchar *measures[n_MEASURES + 1]={
   N_("Nominal"),
   N_("Ordinal"),
   N_("Scale"),
diff --git a/src/ui/gui/var-sheet.h b/src/ui/gui/var-sheet.h
index fda222b9..29df4cdb 100644
--- a/src/ui/gui/var-sheet.h
+++ b/src/ui/gui/var-sheet.h
@@ -50,10 +50,13 @@ GtkWidget* psppire_variable_sheet_create (gchar *widget_name,
 					  gchar *string2,
 					  gint int1, gint int2);
 
+#define n_ALIGNMENTS 3
 
-extern const gchar *alignments[];
+extern const gchar *alignments[n_ALIGNMENTS + 1];
 
-extern const gchar *measures[];
+#define n_MEASURES 3
+
+extern const gchar *measures[n_MEASURES + 1];
 
 
 #endif
-- 
2.30.2