From af5791ea792acc0a9707738001aa1df3daff7a66 Mon Sep 17 00:00:00 2001
From: Mike Gorse <mgorse@suse.com>
Date: Wed, 30 Aug 2017 15:13:09 -0500
Subject: [PATCH 3/4] Fix possible use after free when calling
 compileBrailleIndicator

CompileBrailleIndicator calls addRule, which may realloc the table header,
so it is unsafe to pass an out parameter under the assumption that the
value of table will not change.

Fixes CVE-2017-13741.
---
diff -urp liblouis-1.7.0.orig/liblouis/compileTranslationTable.c liblouis-1.7.0/liblouis/compileTranslationTable.c
--- liblouis-1.7.0.orig/liblouis/compileTranslationTable.c	2017-09-07 15:19:54.105158963 -0500
+++ liblouis-1.7.0/liblouis/compileTranslationTable.c	2017-09-07 16:44:47.983082178 -0500
@@ -2910,6 +2910,7 @@ compileRule (FileInfo * nested)
   TranslationTableCharacterAttributes after = 0;
   TranslationTableCharacterAttributes before = 0;
   int k;
+  TranslationTableOffset tmp_offset;
 
   noback = nofor = 0;
 doOpcode:
@@ -2943,44 +2944,56 @@ doOpcode:
       break;
 
     case CTO_CapitalSign:
+      tmp_offset = table->capitalSign;
       ok = compileBrailleIndicator (nested,
 				    "capital sign", CTO_CapitalRule,
-				    &table->capitalSign);
+				    &tmp_offset);
+      table->capitalSign = tmp_offset;
       break;
     case CTO_BeginCapitalSign:
+      tmp_offset = table->beginCapitalSign;
       ok = compileBrailleIndicator (nested,
 				    "begin capital sign",
 				    CTO_BeginCapitalRule,
-				    &table->beginCapitalSign);
+				    &tmp_offset);
+      table->beginCapitalSign = tmp_offset;
       break;
     case CTO_LenBegcaps:
       ok = table->lenBeginCaps = compileNumber (nested);
       break;
     case CTO_EndCapitalSign:
+      tmp_offset = table->endCapitalSign;
       ok = compileBrailleIndicator (nested,
 				    "end capitals sign",
 				    CTO_EndCapitalRule,
-				    &table->endCapitalSign);
+				    &tmp_offset);
+      table->endCapitalSign = tmp_offset;
       break;
     case CTO_FirstWordCaps:
+      tmp_offset = table->firstWordCaps;
       ok = compileBrailleIndicator (nested,
 				    "first word capital sign",
 				    CTO_FirstWordCapsRule,
-				    &table->firstWordCaps);
+				    &tmp_offset);
+      table->firstWordCaps = tmp_offset;
       break;
     case CTO_LastWordCapsAfter:
+      tmp_offset = table->lastWordCapsAfter;
       ok = compileBrailleIndicator (nested,
 				    "capital sign after last word",
 				    CTO_LastWordCapsAfterRule,
-				    &table->lastWordCapsAfter);
+				    &tmp_offset);
+      table->lastWordCapsAfter = tmp_offset;
       break;
     case CTO_LenCapsPhrase:
       ok = table->lenCapsPhrase = compileNumber (nested);
       break;
     case CTO_LetterSign:
+      tmp_offset = table->letterSign;
       ok = compileBrailleIndicator (nested,
 				    "letter sign", CTO_LetterRule,
-				    &table->letterSign);
+				    &tmp_offset);
+      table->letterSign = tmp_offset;
       break;
     case CTO_NoLetsignBefore:
       if (getRuleCharsText (nested, &ruleChars))
@@ -3024,155 +3037,203 @@ doOpcode:
 	}
       break;
     case CTO_NumberSign:
+      tmp_offset = table->numberSign;
       ok = compileBrailleIndicator (nested,
 				    "number sign", CTO_NumberRule,
-				    &table->numberSign);
+				    &tmp_offset);
+      table->numberSign = tmp_offset;
       break;
     case CTO_FirstWordItal:
+      tmp_offset = table->firstWordItal;
       ok = compileBrailleIndicator (nested,
 				    "first word italic",
 				    CTO_FirstWordItalRule,
-				    &table->firstWordItal);
+				    &tmp_offset);
+      table->firstWordItal = tmp_offset;
       break;
     case CTO_ItalSign:
     case CTO_LastWordItalBefore:
+      tmp_offset = table->lastWordItalBefore;
       ok = compileBrailleIndicator
 	(nested, "first word italic before",
-	 CTO_LastWordItalBeforeRule, &table->lastWordItalBefore);
+	 CTO_LastWordItalBeforeRule, &tmp_offset);
+      table->lastWordItalBefore = tmp_offset;
       break;
     case CTO_LastWordItalAfter:
+      tmp_offset = table->lastWordItalAfter;
       ok =
 	compileBrailleIndicator (nested, "last word italic after",
 				 CTO_LastWordItalAfterRule,
-				 &table->lastWordItalAfter);
+				 &tmp_offset);
+      table->lastWordItalAfter = tmp_offset;
       break;
     case CTO_BegItal:
     case CTO_FirstLetterItal:
+      tmp_offset = table->firstLetterItal;
       ok = compileBrailleIndicator
 	(nested, "first letter italic", CTO_FirstLetterItalRule,
-	 &table->firstLetterItal);
+	 &tmp_offset);
+      table->firstLetterItal = tmp_offset;
       break;
     case CTO_EndItal:
     case CTO_LastLetterItal:
+      tmp_offset = table->lastLetterItal;
       ok = compileBrailleIndicator (nested,
 				    "last letter italic",
 				    CTO_LastLetterItalRule,
-				    &table->lastLetterItal);
+				    &tmp_offset);
+      table->lastLetterItal = tmp_offset;
       break;
     case CTO_SingleLetterItal:
+      tmp_offset = table->singleLetterItal;
       ok = compileBrailleIndicator (nested,
 				    "single letter italic",
 				    CTO_SingleLetterItalRule,
-				    &table->singleLetterItal);
+				    &tmp_offset);
+      table->singleLetterItal = tmp_offset;
       break;
     case CTO_ItalWord:
+      tmp_offset = table->italWord;
       ok = compileBrailleIndicator (nested,
 				    "italic word",
-				    CTO_ItalWordRule, &table->italWord);
+				    CTO_ItalWordRule, &tmp_offset);
+      table->italWord = tmp_offset;
       break;
     case CTO_LenItalPhrase:
       ok = table->lenItalPhrase = compileNumber (nested);
       break;
     case CTO_FirstWordBold:
+      tmp_offset = table->firstWordBold;
       ok = compileBrailleIndicator
 	(nested, "first word bold", CTO_FirstWordBoldRule,
-	 &table->firstWordBold);
+	 &tmp_offset);
+      table->firstWordBold = tmp_offset;
       break;
     case CTO_BoldSign:
     case CTO_LastWordBoldBefore:
+      tmp_offset = table->lastWordBoldBefore;
       ok = compileBrailleIndicator (nested,
 				    "last word bold before",
 				    CTO_LastWordBoldBeforeRule,
-				    &table->lastWordBoldBefore);
+				    &tmp_offset);
+      table->lastWordBoldBefore = tmp_offset;
       break;
     case CTO_LastWordBoldAfter:
+      tmp_offset = table->lastWordBoldAfter;
       ok = compileBrailleIndicator (nested,
 				    "last word bold after",
 				    CTO_LastWordBoldAfterRule,
-				    &table->lastWordBoldAfter);
+				    &tmp_offset);
+      table->lastWordBoldAfter = tmp_offset;
       break;
     case CTO_BegBold:
     case CTO_FirstLetterBold:
+      tmp_offset = table->firstLetterBold;
       ok = compileBrailleIndicator (nested,
 				    "first  letter bold",
 				    CTO_FirstLetterBoldRule,
-				    &table->firstLetterBold);
+				    &tmp_offset);
+      table->firstLetterBold = tmp_offset;
       break;
     case CTO_EndBold:
     case CTO_LastLetterBold:
+      tmp_offset = table->lastLetterBold;
       ok =
 	compileBrailleIndicator (nested, "last letter bold",
 				 CTO_LastLetterBoldRule,
-				 &table->lastLetterBold);
+				 &tmp_offset);
+      table->lastLetterBold = tmp_offset;
       break;
     case CTO_SingleLetterBold:
+      tmp_offset = table->singleLetterBold;
       ok = compileBrailleIndicator (nested,
 				    "single  letter bold",
 				    CTO_SingleLetterBoldRule,
-				    &table->singleLetterBold);
+				    &tmp_offset);
+      table->singleLetterBold = tmp_offset;
       break;
     case CTO_BoldWord:
+      tmp_offset = table->boldWord;
       ok = compileBrailleIndicator (nested,
 				    "bold word",
-				    CTO_BoldWordRule, &table->boldWord);
+				    CTO_BoldWordRule, &tmp_offset);
+      table->boldWord = tmp_offset;
       break;
     case CTO_LenBoldPhrase:
       ok = table->lenBoldPhrase = compileNumber (nested);
       break;
     case CTO_FirstWordUnder:
+      tmp_offset = table->firstWordUnder;
       ok = compileBrailleIndicator (nested,
 				    "first word  underline",
 				    CTO_FirstWordUnderRule,
-				    &table->firstWordUnder);
+				    &tmp_offset);
+      table->firstWordUnder = tmp_offset;
       break;
     case CTO_UnderSign:
     case CTO_LastWordUnderBefore:
+      tmp_offset = table->lastWordUnderBefore;
       ok =
 	compileBrailleIndicator (nested, "last word underline before",
 				 CTO_LastWordUnderBeforeRule,
-				 &table->lastWordUnderBefore);
+				 &tmp_offset);
+      table->lastWordUnderBefore = tmp_offset;
       break;
     case CTO_LastWordUnderAfter:
+      tmp_offset = table->lastWordUnderAfter;
       ok = compileBrailleIndicator (nested,
 				    "last  word underline after",
 				    CTO_LastWordUnderAfterRule,
-				    &table->lastWordUnderAfter);
+				    &tmp_offset);
+      table->lastWordUnderAfter = tmp_offset;
       break;
     case CTO_BegUnder:
     case CTO_FirstLetterUnder:
+      tmp_offset = table->firstLetterUnder;
       ok = compileBrailleIndicator (nested,
 				    "first letter underline",
 				    CTO_FirstLetterUnderRule,
-				    &table->firstLetterUnder);
+				    &tmp_offset);
+      table->firstLetterUnder = tmp_offset;
       break;
     case CTO_EndUnder:
     case CTO_LastLetterUnder:
+      tmp_offset = table->lastLetterUnder;
       ok = compileBrailleIndicator (nested, "last letter underline",
 				    CTO_LastLetterUnderRule,
-				    &table->lastLetterUnder);
+				    &tmp_offset);
+      table->lastLetterUnder = tmp_offset;
       break;
     case CTO_SingleLetterUnder:
+      tmp_offset = table->singleLetterUnder;
       ok = compileBrailleIndicator (nested,
 				    "single letter underline",
 				    CTO_SingleLetterUnderRule,
-				    &table->singleLetterUnder);
+				    &tmp_offset);
+      table->singleLetterUnder = tmp_offset;
       break;
     case CTO_UnderWord:
+      tmp_offset = table->underWord;
       ok = compileBrailleIndicator (nested,
 				    "underlined word",
-				    CTO_UnderWordRule, &table->underWord);
+				    CTO_UnderWordRule, &tmp_offset);
+      table->underWord = tmp_offset;
       break;
     case CTO_LenUnderPhrase:
       ok = table->lenUnderPhrase = compileNumber (nested);
       break;
     case CTO_BegComp:
+      tmp_offset = table->begComp;
       ok = compileBrailleIndicator (nested, "begin computer braille",
-				    CTO_BegCompRule, &table->begComp);
+				    CTO_BegCompRule, &tmp_offset);
+      table->begComp = tmp_offset;
       break;
     case CTO_EndComp:
+      tmp_offset = table->endComp;
       ok = compileBrailleIndicator (nested,
 				    "end computer braslle",
-				    CTO_EndCompRule, &table->endComp);
+				    CTO_EndCompRule, &tmp_offset);
+      table->endComp = tmp_offset;
       break;
 
     case CTO_Syllable:
