From 73751be7a5617bfff4a735ae095203a2d3ec50ef Mon Sep 17 00:00:00 2001
From: Martin Gieseking <martin.gieseking@uos.de>
Date: Tue, 22 Mar 2022 15:31:04 +0100
Subject: [PATCH] Prevent writing past CharString memory in compilePassOpcode

---
diff -urp liblouis-3.3.0.orig/liblouis/compileTranslationTable.c liblouis-3.3.0/liblouis/compileTranslationTable.c
--- liblouis-3.3.0.orig/liblouis/compileTranslationTable.c	2022-06-03 12:33:24.500790783 -0500
+++ liblouis-3.3.0/liblouis/compileTranslationTable.c	2022-06-03 16:32:56.920660612 -0500
@@ -2517,6 +2517,17 @@ verifyStringOrDots (FileInfo *nested, Tr
 }
 
 static int
+appendInstructionChar(
+		const FileInfo *file, widechar *passInstructions, int *passIC, widechar ch) {
+	if (*passIC >= MAXSTRING) {
+		compileError(file, "multipass operand too long");
+		return 0;
+	}
+	passInstructions[(*passIC)++] = ch;
+	return 1;
+}
+
+static int
 compilePassOpcode (FileInfo * nested,
 		   TranslationTableOpcode opcode,
 		   CharacterClass *characterClasses,
@@ -2612,34 +2623,44 @@ compilePassOpcode (FileInfo * nested,
 	  switch (passCode)
 	    {
 	    case pass_not:
-	      passInstructions[passIC++] = pass_not;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_not))
+				return 0;
 	      break;
 	    case pass_first:
-	      passInstructions[passIC++] = pass_first;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_first))
+				return 0;
 	      break;
 	    case pass_last:
-	      passInstructions[passIC++] = pass_last;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_last))
+				return 0;
 	      break;
 	    case pass_search:
-	      passInstructions[passIC++] = pass_search;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_search))
+					return 0;
 	      break;
 	    case pass_string:
 	      if (!verifyStringOrDots(nested, opcode, 1, 0, nofor))
 		{
 		  return 0;
 		}
-	      passInstructions[passIC++] = pass_string;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_string))
+				return 0;
 	      goto ifDoCharsDots;
 	    case pass_dots:
 	      if (!verifyStringOrDots(nested, opcode, 0, 0, nofor))
 		{
 		  return 0;
 		}
-	      passInstructions[passIC++] = pass_dots;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_dots))
+				return 0;
 	    ifDoCharsDots:
-	      passInstructions[passIC++] = passHoldString.length;
+			if (!appendInstructionChar(
+						passNested, passInstructions, &passIC, passHoldString.length))
+				return 0;
 	      for (kk = 0; kk < passHoldString.length; kk++)
-		passInstructions[passIC++] = passHoldString.chars[kk];
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, passHoldString.chars[kk]))
+					return 0;
 	      break;
 	    case pass_attributes:
 	      if (!passIsLeftParen (&passLine, &passLinepos, &passPrevLinepos, &passHoldString, passNested))
@@ -2657,11 +2678,13 @@ compilePassOpcode (FileInfo * nested,
 	      /*Right parenthis handled by subfunctiion */
 	      break;
 	    case pass_lookback:
-	      passInstructions[passIC++] = pass_lookback;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_lookback))
+				return 0;
 	      passCode = passGetScriptToken (&passLine, &passLinepos, &passPrevLinepos, &passHoldString, &passHoldNumber, passNested);
 	      if (passCode != pass_leftParen)
 		{
-		  passInstructions[passIC++] = 1;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, 1))
+				return 0;
 		  passLinepos = passPrevLinepos;
 		  break;
 		}
@@ -2669,23 +2692,32 @@ compilePassOpcode (FileInfo * nested,
 		return 0;
 	      if (!passIsRightParen (&passLine, &passLinepos, &passPrevLinepos, &passHoldString, passNested))
 		return 0;
-	      passInstructions[passIC] = passHoldNumber;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, passHoldNumber))
+				return 0;
 	      break;
 	    case pass_group:
 	      if (!passIsLeftParen (&passLine, &passLinepos, &passPrevLinepos, &passHoldString, passNested))
 		return 0;
 	      break;
 	    case pass_mark:
-	      passInstructions[passIC++] = pass_startReplace;
-	      passInstructions[passIC++] = pass_endReplace;
+			if (!appendInstructionChar(
+						passNested, passInstructions, &passIC, pass_startReplace))
+				return 0;
+			if (!appendInstructionChar(
+						passNested, passInstructions, &passIC, pass_endReplace))
+				return 0;
 	      break;
 	    case pass_replace:
-	      passInstructions[passIC++] = pass_startReplace;
+			if (!appendInstructionChar(
+						passNested, passInstructions, &passIC, pass_startReplace))
+				return 0;
 	      if (!passIsLeftParen (&passLine, &passLinepos, &passPrevLinepos, &passHoldString, passNested))
 		return 0;
 	      break;
 	    case pass_rightParen:
-	      passInstructions[passIC++] = pass_endReplace;
+			if (!appendInstructionChar(
+						passNested, passInstructions, &passIC, pass_endReplace))
+				return 0;
 	      break;
 	    case pass_groupstart:
 	    case pass_groupend:
@@ -2700,9 +2732,14 @@ compilePassOpcode (FileInfo * nested,
 		rule = (TranslationTableRule *) & table->ruleArea[ruleOffset];
 	      if (rule && rule->opcode == CTO_Grouping)
 		{
-		  passInstructions[passIC++] = passSubOp;
-		  passInstructions[passIC++] = ruleOffset >> 16;
-		  passInstructions[passIC++] = ruleOffset & 0xffff;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, passSubOp))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset >> 16))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset & 0xffff))
+					return 0;
 		  break;
 		}
 	      else
@@ -2740,9 +2777,14 @@ compilePassOpcode (FileInfo * nested,
 		  && (rule->opcode == CTO_SwapCc || rule->opcode == CTO_SwapCd
 		      || rule->opcode == CTO_SwapDd))
 		{
-		  passInstructions[passIC++] = pass_swap;
-		  passInstructions[passIC++] = ruleOffset >> 16;
-		  passInstructions[passIC++] = ruleOffset & 0xffff;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_swap))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset >> 16))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset & 0xffff))
+					return 0;
 		  if (!passGetRange (&passLine, &passLinepos, &passPrevLinepos, &passHoldString, passNested, passInstructions, &passIC))
 		    return 0;
 		  break;
@@ -2763,14 +2805,18 @@ compilePassOpcode (FileInfo * nested,
 				"invalid comparison operator in if part");
 		  return 0;
 		}
-	      passInstructions[passIC++] = passCode;
-	      passInstructions[passIC++] = passHoldNumber;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, passCode))
+					return 0;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, passHoldNumber))
+					return 0;
 	      if (!passIsNumber (&passLine, &passLinepos, &passPrevLinepos, &passHoldString, &passHoldNumber, passNested))
 		return 0;
-	      passInstructions[passIC++] = passHoldNumber;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, passHoldNumber))
+				return 0;
 	      break;
 	    case pass_then:
-	      passInstructions[passIC++] = pass_endTest;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_endTest))
+				return 0;
 	      more = 0;
 	      break;
 	    default:
@@ -2792,18 +2838,23 @@ compilePassOpcode (FileInfo * nested,
 		{
 		  return 0;
 		}
-	      passInstructions[passIC++] = pass_string;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_string))
+				return 0;
 	      goto thenDoCharsDots;
 	    case pass_dots:
 	      if (!verifyStringOrDots(nested, opcode, 0, 1, nofor))
 		{
 		  return 0;
 		}
-	      passInstructions[passIC++] = pass_dots;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_dots))
+				return 0;
 	    thenDoCharsDots:
-	      passInstructions[passIC++] = passHoldString.length;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, passHoldString.length))
+				return 0;
 	      for (kk = 0; kk < passHoldString.length; kk++)
-		passInstructions[passIC++] = passHoldString.chars[kk];
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, passHoldString.chars[kk]))
+					return 0;
 	      break;
 	    case pass_nameFound:
 	      passHoldNumber = passFindName (&passHoldString, passNested, &passOpcode);
@@ -2815,17 +2866,22 @@ compilePassOpcode (FileInfo * nested,
 				"Invalid variable operator in then part");
 		  return 0;
 		}
-	      passInstructions[passIC++] = passCode;
-	      passInstructions[passIC++] = passHoldNumber;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, passCode))
+				return 0;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, passHoldNumber))
+				return 0;
 	      if (!passIsNumber (&passLine, &passLinepos, &passPrevLinepos, &passHoldString, &passHoldNumber, passNested))
 		return 0;
-	      passInstructions[passIC++] = passHoldNumber;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, passHoldNumber))
+				return 0;
 	      break;
 	    case pass_copy:
-	      passInstructions[passIC++] = pass_copy;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_copy))
+				return 0;
 	      break;
 	    case pass_omit:
-	      passInstructions[passIC++] = pass_omit;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_omit))
+				return 0;
 	      break;
 	    case pass_swap:
 	      ruleOffset = findRuleName (&passHoldString, ruleNames);
@@ -2842,9 +2898,14 @@ compilePassOpcode (FileInfo * nested,
 		  && (rule->opcode == CTO_SwapCc || rule->opcode == CTO_SwapCd
 		      || rule->opcode == CTO_SwapDd))
 		{
-		  passInstructions[passIC++] = pass_swap;
-		  passInstructions[passIC++] = ruleOffset >> 16;
-		  passInstructions[passIC++] = ruleOffset & 0xffff;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_swap))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset >> 16))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset & 0xffff))
+					return 0;
 		  if (!passGetRange (&passLine, &passLinepos, &passPrevLinepos, &passHoldString, passNested, passInstructions, &passIC))
 		    return 0;
 		  break;
@@ -2874,34 +2935,36 @@ compilePassOpcode (FileInfo * nested,
       passLinepos = 0;
       while (passLinepos <= endTest)
 	{
-			if (passIC >= MAXSTRING) {
-				compileError(passNested, "Test part in multipass operand too long");
-				return 0;
-			}
 	  switch ((passSubOp = passLine.chars[passLinepos]))
 	    {
 	    case pass_lookback:
-	      passInstructions[passIC++] = pass_lookback;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_lookback))
+				return 0;
 	      passLinepos++;
 	      passGetNumber (&passLine, &passLinepos, &passHoldNumber);
 	      if (passHoldNumber == 0)
 		passHoldNumber = 1;
-	      passInstructions[passIC++] = passHoldNumber;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, passHoldNumber))
+				return 0;
 	      break;
 	    case pass_not:
-	      passInstructions[passIC++] = pass_not;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_not))
+				return 0;
 	      passLinepos++;
 	      break;
 	    case pass_first:
-	      passInstructions[passIC++] = pass_first;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_first))
+				return 0;
 	      passLinepos++;
 	      break;
 	    case pass_last:
-	      passInstructions[passIC++] = pass_last;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_last))
+				return 0;
 	      passLinepos++;
 	      break;
 	    case pass_search:
-	      passInstructions[passIC++] = pass_search;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_search))
+				return 0;
 	      passLinepos++;
 	      break;
 	    case pass_string:
@@ -2910,7 +2973,8 @@ compilePassOpcode (FileInfo * nested,
 		  return 0;
 		}
 	      passLinepos++;
-	      passInstructions[passIC++] = pass_string;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_string))
+				return 0;
 	      passGetString (&passLine, &passLinepos, &passHoldString, passNested);
 	      goto testDoCharsDots;
 	    case pass_dots:
@@ -2919,21 +2983,29 @@ compilePassOpcode (FileInfo * nested,
 		  return 0;
 		}
 	      passLinepos++;
-	      passInstructions[passIC++] = pass_dots;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_dots))
+				return 0;
 	      passGetDots (&passLine, &passLinepos, &passHoldString, passNested);
 	    testDoCharsDots:
 	      if (passHoldString.length == 0)
 		return 0;
-	      passInstructions[passIC++] = passHoldString.length;
+			if (!appendInstructionChar(
+						passNested, passInstructions, &passIC, passHoldString.length))
+				return 0;
 	      for (kk = 0; kk < passHoldString.length; kk++)
-		passInstructions[passIC++] = passHoldString.chars[kk];
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, passHoldString.chars[kk]))
+					return 0;
 	      break;
 	    case pass_startReplace:
-	      passInstructions[passIC++] = pass_startReplace;
+			if (!appendInstructionChar(
+						passNested, passInstructions, &passIC, pass_startReplace))
+				return 0;
 	      passLinepos++;
 	      break;
 	    case pass_endReplace:
-	      passInstructions[passIC++] = pass_endReplace;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_endReplace))
+				return 0;
 	      passLinepos++;
 	      break;
 	    case pass_variable:
@@ -2943,30 +3015,39 @@ compilePassOpcode (FileInfo * nested,
 	      switch (passLine.chars[passLinepos])
 		{
 		case pass_eq:
-		  passInstructions[passIC++] = pass_eq;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_eq))
+					return 0;
 		  goto doComp;
 		case pass_lt:
 		  if (passLine.chars[passLinepos + 1] == pass_eq)
 		    {
 		      passLinepos++;
-		      passInstructions[passIC++] = pass_lteq;
-		    }
-		  else
-		    passInstructions[passIC++] = pass_lt;
+					if (!appendInstructionChar(
+								passNested, passInstructions, &passIC, pass_lteq))
+						return 0;
+				} else if (!appendInstructionChar(
+								   passNested, passInstructions, &passIC, pass_lt))
+					return 0;
 		  goto doComp;
 		case pass_gt:
 		  if (passLine.chars[passLinepos + 1] == pass_eq)
 		    {
 		      passLinepos++;
-		      passInstructions[passIC++] = pass_gteq;
-		    }
-		  else
-		    passInstructions[passIC++] = pass_gt;
+					if (!appendInstructionChar(
+								passNested, passInstructions, &passIC, pass_gteq))
+						return 0;
+				} else if (!appendInstructionChar(
+								   passNested, passInstructions, &passIC, pass_gt))
+					return 0;
 		doComp:
-		  passInstructions[passIC++] = passHoldNumber;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, passHoldNumber))
+					return 0;
 		  passLinepos++;
 		  passGetNumber (&passLine, &passLinepos, &passHoldNumber);
-		  passInstructions[passIC++] = passHoldNumber;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, passHoldNumber))
+					return 0;
 		  break;
 		default:
 		  compileError (passNested, "incorrect comparison operator");
@@ -2978,28 +3059,37 @@ compilePassOpcode (FileInfo * nested,
 	      if (!passGetAttributes(&passLine, &passLinepos, &passAttributes, passNested))
                 return 0;
 	    insertAttributes:
-	      passInstructions[passIC++] = pass_attributes;
-	      passInstructions[passIC++] = passAttributes >> 16;
-	      passInstructions[passIC++] = passAttributes & 0xffff;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_attributes))
+				return 0;
+			if (!appendInstructionChar(
+						passNested, passInstructions, &passIC, (passAttributes >> 16) & 0xffff))
+				return 0;
+			if (!appendInstructionChar(
+						passNested, passInstructions, &passIC, passAttributes & 0xffff))
+				return 0;
 	    getRange:
 	      if (passLine.chars[passLinepos] == pass_until)
 		{
 		  passLinepos++;
-		  passInstructions[passIC++] = 1;
-		  passInstructions[passIC++] = 0xffff;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, 1)) return 0;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, 0xffff))
+					return 0;
 		  break;
 		}
 	      passGetNumber (&passLine, &passLinepos, &passHoldNumber);
 	      if (passHoldNumber == 0)
 		{
-		  passHoldNumber = passInstructions[passIC++] = 1;
-		  passInstructions[passIC++] = 1;	/*This is not an error */
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, 1)) return 0;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, 1)) return 0;
 		  break;
 		}
-	      passInstructions[passIC++] = passHoldNumber;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, passHoldNumber))
+				return 0;
 	      if (passLine.chars[passLinepos] != pass_hyphen)
 		{
-		  passInstructions[passIC++] = passHoldNumber;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, passHoldNumber))
+					return 0;
 		  break;
 		}
 	      passLinepos++;
@@ -3009,7 +3099,8 @@ compilePassOpcode (FileInfo * nested,
 		  compileError (passNested, "invalid range");
 		  return 0;
 		}
-	      passInstructions[passIC++] = passHoldNumber;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, passHoldNumber))
+				return 0;
 	      break;
 	    case pass_groupstart:
 	    case pass_groupend:
@@ -3020,9 +3111,14 @@ compilePassOpcode (FileInfo * nested,
 		rule = (TranslationTableRule *) & table->ruleArea[ruleOffset];
 	      if (rule && rule->opcode == CTO_Grouping)
 		{
-		  passInstructions[passIC++] = passSubOp;
-		  passInstructions[passIC++] = ruleOffset >> 16;
-		  passInstructions[passIC++] = ruleOffset & 0xffff;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, passSubOp))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset >> 16))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset & 0xffff))
+					return 0;
 		  break;
 		}
 	      else
@@ -3047,9 +3143,14 @@ compilePassOpcode (FileInfo * nested,
 		  && (rule->opcode == CTO_SwapCc || rule->opcode == CTO_SwapCd
 		      || rule->opcode == CTO_SwapDd))
 		{
-		  passInstructions[passIC++] = pass_swap;
-		  passInstructions[passIC++] = ruleOffset >> 16;
-		  passInstructions[passIC++] = ruleOffset & 0xffff;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_swap))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset >> 16))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset & 0xffff))
+					return 0;
 		  goto getRange;
 		}
 	      compileError (passNested,
@@ -3058,7 +3159,8 @@ compilePassOpcode (FileInfo * nested,
 					passHoldString.length));
 	      return 0;
 	    case pass_endTest:
-	      passInstructions[passIC++] = pass_endTest;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_endTest))
+				return 0;
 	      passLinepos++;
 	      break;
 	    default:
@@ -3089,7 +3191,8 @@ compilePassOpcode (FileInfo * nested,
 		  return 0;
 		}
 	      passLinepos++;
-	      passInstructions[passIC++] = pass_string;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_string))
+				return 0;
 	      passGetString (&passLine, &passLinepos, &passHoldString, passNested);
 	      goto actionDoCharsDots;
 	    case pass_dots:
@@ -3099,18 +3202,23 @@ compilePassOpcode (FileInfo * nested,
 		}
 	      passLinepos++;
 	      passGetDots (&passLine, &passLinepos, &passHoldString, passNested);
-	      passInstructions[passIC++] = pass_dots;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_dots))
+				return 0;
 	    actionDoCharsDots:
 	      if (passHoldString.length == 0)
 		return 0;
-	      passInstructions[passIC++] = passHoldString.length;
+			if (!appendInstructionChar(
+						passNested, passInstructions, &passIC, passHoldString.length))
+				return 0;
 				for (kk = 0; kk < passHoldString.length; kk++) {
 					if (passIC >= MAXSTRING) {
 						compileError(passNested,
 								"@ operand in action part of multipass operand too long");
 						return 0;
 					}
-		passInstructions[passIC++] = passHoldString.chars[kk];
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, passHoldString.chars[kk]))
+					return 0;
 				}
 	      break;
 	    case pass_variable:
@@ -3120,16 +3228,25 @@ compilePassOpcode (FileInfo * nested,
 	      switch (passLine.chars[passLinepos])
 		{
 		case pass_eq:
-		  passInstructions[passIC++] = pass_eq;
-		  passInstructions[passIC++] = passHoldNumber;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_eq))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, passHoldNumber))
+					return 0;
 		  passLinepos++;
 		  passGetNumber (&passLine, &passLinepos, &passHoldNumber);
-		  passInstructions[passIC++] = passHoldNumber;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, passHoldNumber))
+					return 0;
 		  break;
 		case pass_plus:
 		case pass_hyphen:
-		  passInstructions[passIC++] = passLine.chars[passLinepos++];
-		  passInstructions[passIC++] = passHoldNumber;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC,
+							passLine.chars[passLinepos++]))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, passHoldNumber))
+					return 0;
 		  break;
 		default:
 		  compileError (passNested,
@@ -3138,11 +3255,13 @@ compilePassOpcode (FileInfo * nested,
 		}
 	      break;
 	    case pass_copy:
-	      passInstructions[passIC++] = pass_copy;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_copy))
+				return 0;
 	      passLinepos++;
 	      break;
 	    case pass_omit:
-	      passInstructions[passIC++] = pass_omit;
+			if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_omit))
+				return 0;
 	      passLinepos++;
 	      break;
 	    case pass_groupreplace:
@@ -3155,9 +3274,14 @@ compilePassOpcode (FileInfo * nested,
 		rule = (TranslationTableRule *) & table->ruleArea[ruleOffset];
 	      if (rule && rule->opcode == CTO_Grouping)
 		{
-		  passInstructions[passIC++] = passSubOp;
-		  passInstructions[passIC++] = ruleOffset >> 16;
-		  passInstructions[passIC++] = ruleOffset & 0xffff;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, passSubOp))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset >> 16))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset & 0xffff))
+					return 0;
 		  break;
 		}
 	      compileError (passNested, "%s is not a grouping name",
@@ -3174,9 +3298,14 @@ compilePassOpcode (FileInfo * nested,
 		  && (rule->opcode == CTO_SwapCc || rule->opcode == CTO_SwapCd
 		      || rule->opcode == CTO_SwapDd))
 		{
-		  passInstructions[passIC++] = pass_swap;
-		  passInstructions[passIC++] = ruleOffset >> 16;
-		  passInstructions[passIC++] = ruleOffset & 0xffff;
+				if (!appendInstructionChar(passNested, passInstructions, &passIC, pass_swap))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset >> 16))
+					return 0;
+				if (!appendInstructionChar(
+							passNested, passInstructions, &passIC, ruleOffset & 0xffff))
+					return 0;
 		  break;
 		}
 	      compileError (passNested, "%s is not a swap name.",
Only in liblouis-3.3.0/liblouis: compileTranslationTable.c.rej
