* src/truetype/ttgload.c (TT_Load_Simple_Glyph): check the well-formedness
	of the contours array when loading a glyph

	* src/truetype/ttinterp.c (Ins_IP): check argument ranges to reject
	bogus operations properly
diff --git a/ChangeLog b/ChangeLog
index 2ae2699..61e3968 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,12 @@
 	* src/smooth/ftgrays.c (gray_hline): prevent integer overflows
 	when rendering *very* large outlines
 
+	* src/truetype/ttgload.c (TT_Load_Simple_Glyph): check the well-formedness
+	of the contours array when loading a glyph
+
+	* src/truetype/ttinterp.c (Ins_IP): check argument ranges to reject
+	bogus operations properly
+
 
 2006-06-16  Dmitry Timoshkov  <dmitry@codeweavers.com>
 
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 8947055..90e4385 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -250,7 +250,7 @@
     FT_Byte         c, count;
     FT_Vector       *vec, *vec_limit;
     FT_Pos          x;
-    FT_Short        *cont, *cont_limit;
+    FT_Short        *cont, *cont_limit, prev_cont;
     FT_Int          xy_size = 0;
 
 
@@ -267,8 +267,18 @@
     if ( n_contours >= 0xFFF || p + (n_contours + 1) * 2 > limit )
       goto Invalid_Outline;
 
-    for ( ; cont < cont_limit; cont++ )
+    cont[0] = prev_cont = FT_NEXT_USHORT( p );
+    for ( cont++; cont < cont_limit; cont++ )
+    {
       cont[0] = FT_NEXT_USHORT( p );
+      if (cont[0] > prev_cont)
+      {
+        /* unordered contours, this is invalid */
+        error = FT_Err_Invalid_Table;
+        goto Fail;
+      }
+      prev_cont = cont[0];
+    }
 
     n_points = 0;
     if ( n_contours > 0 )
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 31adb50..080337c 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -620,6 +620,9 @@
 
     exec->pts.n_points   = 0;
     exec->pts.n_contours = 0;
+    exec->zp1 = exec->pts;
+    exec->zp2 = exec->pts;
+    exec->zp0 = exec->pts;
 
     exec->instruction_trap = FALSE;
 
@@ -6148,6 +6151,13 @@
      */
     twilight = CUR.GS.gep0 == 0 || CUR.GS.gep1 == 0 || CUR.GS.gep2 == 0;
 
+    if ( BOUNDS(CUR.GS.rp1, CUR.zp0.n_points) )
+    {
+      if ( CUR.pedantic_hinting )
+        CUR.error = TT_Err_Invalid_Reference;
+      return;
+    }
+
     if ( twilight )
       orus_base = &CUR.zp0.org[CUR.GS.rp1];
     else
@@ -6251,6 +6261,7 @@
     FT_Vector*  orgs;   /* original and current coordinate */
     FT_Vector*  curs;   /* arrays                          */
     FT_Vector*  orus;
+    FT_UInt     max_points;
 
   } IUP_WorkerRec, *IUP_Worker;
 
@@ -6291,6 +6302,10 @@
     if ( p1 > p2 )
       return;
 
+    if ( BOUNDS(ref1, worker->max_points) ||
+         BOUNDS(ref2, worker->max_points) )
+      return;
+
     orus1 = worker->orus[ref1].x;
     orus2 = worker->orus[ref2].x;
 
@@ -6389,6 +6404,9 @@
 
     FT_UNUSED_ARG;
 
+    /* ignore empty outlines */
+    if ( CUR.pts.n_contours == 0 )
+      return;
 
     if ( CUR.opcode & 1 )
     {