As it happened, I had a prepared a similar patch.  Attached.
Perhaps we could compare patches.

J'

On Sat, May 05, 2012 at 10:14:57PM -0700, Ben Pfaff wrote:
     John Darrington <j...@darrington.wattle.id.au> writes:
     
     > Looking at the bug recently reported on bug-gnu-pspp I notice the 
following.
     >
     > Valgrind reports:
     
     I sent out a 2-patch series that fixes the problem that I see,
     with and without valgrind.  Does it fix the problem you see too?
     
     Thanks,
     
     Ben.

-- 
PGP Public key ID: 1024D/2DE827B3 
fingerprint = 8797 A26D 0854 2EAB 0285  A290 8A67 719C 2DE8 27B3
See http://keys.gnupg.net or any PGP keyserver for public key.

diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c
index e72a3e4..7048d8a 100644
--- a/src/language/lexer/lexer.c
+++ b/src/language/lexer/lexer.c
@@ -1217,6 +1217,9 @@ lex_source_read__ (struct lex_source *src)
       n = src->reader->class->read (src->reader, &src->buffer[head_ofs],
                                     src->allocated - head_ofs,
                                     segmenter_get_prompt (&src->segmenter));
+
+      assert (n <= src->allocated - head_ofs);
+
       if (n == 0)
         {
           /* End of input.
diff --git a/src/ui/gui/psppire-lex-reader.c b/src/ui/gui/psppire-lex-reader.c
index ae043b0..6351094 100644
--- a/src/ui/gui/psppire-lex-reader.c
+++ b/src/ui/gui/psppire-lex-reader.c
@@ -66,26 +66,47 @@ lex_gtk_text_buffer_read (struct lex_reader *r_, char *buf, size_t n,
                  enum prompt_style prompt_style UNUSED)
 {
   struct lex_gtk_text_buffer_reader *r = lex_gtk_text_buffer_reader_cast (r_);
-  int n_chars = n;
   char *s;
 
   GtkTextIter iter = r->start ;
   
-  int offset = gtk_text_iter_get_offset (&iter);
-  int end_offset = gtk_text_iter_get_offset (&r->stop);
-
-  if ( end_offset - offset < n)
-    n_chars = end_offset - offset;
-  
-  gtk_text_iter_set_offset (&iter, offset + n_chars);
-
-  s = gtk_text_iter_get_text (&r->start, &iter);
-
-  strncpy (buf, s, n_chars);
+  const gint offset = gtk_text_iter_get_offset (&iter);
+  const gint end_offset = gtk_text_iter_get_offset (&r->stop);
+  const gint n_bytes = (end_offset - offset < n) ? end_offset - offset : n;
+
+  /* We want to get no more than n_bytes from the buffer.
+     However, since gtk_text_iter deals in chars, not bytes, we cannot possibly
+     set an iter which we know will not fetch too many bytes.  Thus, we start
+     by assuming that n_chars == n_bytes and step backwards if we end up fetching
+     too many.
+   */
+  gint n_chars = n_bytes;
+  gint backstep = 4;
+  gint bytes_read = 0;
+  do
+    {
+      gtk_text_iter_set_offset (&iter, offset + n_chars);
+
+      s = gtk_text_iter_get_text (&r->start, &iter);
+      bytes_read = strlen (s);
+      if ( n_chars == 1 && bytes_read > n_bytes)
+	{
+	  g_critical ("Reading a single character returned %d bytes, but only %d bytes"
+		      " were requested", bytes_read, n_bytes);
+	  return 0;
+	}
+      n_chars -= backstep;
+      if ( n_chars < 1)
+	n_chars = 1;
+      backstep *= 2;
+    }
+  while (bytes_read > n_bytes);
+
+  strncpy (buf, s, bytes_read);
 
   r->start = iter;
 
-  return strlen (s);
+  return bytes_read;
 }
 
 

Attachment: signature.asc
Description: Digital signature

_______________________________________________
pspp-dev mailing list
pspp-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/pspp-dev

Reply via email to