FS#14019: Detect and reject outdated binary language files (WIP)

Accomplish this by checksumming the english language input
and (1) including that in binary files and (2) checking the
value matches what was compiled into the firmware image

Not sure if this is the best approach but it works.

Change-Id: I8f79ad1b9d1cdf69e6a085d7b3dd1b5e078af04b
This commit is contained in:
Solomon Peachy 2026-09-29 20:22:45 -04:00
parent 265cf7ac92
commit c0ae6c7cd1
3 changed files with 28 additions and 11 deletions

View file

@ -20,18 +20,18 @@ CLEANOBJS += $(BUILDDIR)/lang/max_language_size.h $(BUILDDIR)/lang/lang*
#DUMMY := $(shell mkdir -p $(BUILDDIR)/apps/lang)
# Calculate the maximum language size. Currently based on the file size
# of the largest lng file. Subtract 10 due to HEADER_SIZE and
# of the largest lng file. Subtract 11 due to HEADER_SIZE and
# SUBHEADER_SIZE.
# TODO: In the future generate this file within genlang or another script
# in order to only calculate the maximum size based on the core strings.
$(BUILDDIR)/lang/max_language_size.h: $(LANGOBJ) $(BUILDDIR)/apps/lang/voicestrings.zip
$(call PRINTS,GEN $(subst $(BUILDDIR)/,,$@))
$(SILENT)echo "#define MAX_LANGUAGE_SIZE `ls -ln $(BUILDDIR)/apps/lang/*.lng | awk '{print $$5-10}' | sort -n | tail -1`" > $@
$(SILENT)echo "#define MAX_LANGUAGE_SIZE `ls -ln $(BUILDDIR)/apps/lang/*.lng | awk '{print $$5-11}' | sort -n | tail -1`" > $@
$(BUILDDIR)/lang/lang_core.o: $(BUILDDIR)/lang/lang.h $(BUILDDIR)/lang/lang_core.c
$(call PRINTS,CC lang_core.c)$(CC) $(CFLAGS) -c $(BUILDDIR)/lang/lang_core.c -o $@
# genlang creates *both* lang.c and lang.h but in Make there is no wat to express this rule
# genlang creates *both* lang.c and lang.h but in Make there is no way to express this rule
# (multiple target rules DO NOT express that, they are a simple shortcut for multiple rules)
# instead we pretend that genlang create lang_core.c and that lang.c depends from lang.h
# it will work fine as long as one never manually removes lang.c and not lang.h, and it will avoid

View file

@ -35,12 +35,12 @@
/* These defines must match the initial bytes in the binary lang file */
/* See tools/genlang (TODO: Use common include for both) */
#define LANGUAGE_COOKIE 0x1a
#define LANGUAGE_VERSION 0x06
#define LANGUAGE_VERSION 0x07
#define LANGUAGE_FLAG_RTL 0x01
#define LANGUAGE_FLAG_UNITS_FIRST 0x02
#define HEADER_SIZE 4
#define HEADER_SIZE 5
#define SUBHEADER_SIZE 6
static unsigned char language_buffer[MAX_LANGUAGE_SIZE];
@ -72,8 +72,9 @@ int lang_load(const char *filename, const unsigned char *builtin,
if(read(fd, lang_header, HEADER_SIZE) == HEADER_SIZE &&
((lang_header[0] == LANGUAGE_COOKIE) &&
(lang_header[1] == LANGUAGE_VERSION) &&
(lang_header[2] == TARGET_ID))) {
(lang_header[1] == LANGUAGE_VERSION) &&
(lang_header[2] == TARGET_ID) &&
(lang_header[4] == ENGLISH_LANG_CHECKSUM)) ) {
/* jump to the proper entry in the table of subheaders */
lseek(fd, user_num * SUBHEADER_SIZE, SEEK_CUR);
if (read(fd, sub_header, SUBHEADER_SIZE) != SUBHEADER_SIZE)

View file

@ -9,11 +9,14 @@
# Copyright (C) 2006 - 2008 by Daniel Stenberg
#
use Digest::SHA1;
# See apps/language.c (TODO: Use common include for both)
# Cookie and binary version for the binary lang file
my $LANGUAGE_COOKIE = 0x1a;
my $LANGUAGE_VERSION = 0x07;
my $VOICE_COOKIE = 0x9a;
my $LANGUAGE_VERSION = 0x06;
my $VOICE_VERSION = 0x06;
my $LANGUAGE_FLAG_RTL = 0x01;
my $LANGUAGE_FLAG_UNITS_FIRST = 0x02;
@ -70,6 +73,16 @@ if (!$english) {
print STDERR "Please specify the english lang source (with -e)!\n";
exit;
}
my $english_crc;
{
open my $fh, "<$english" or die $!;
binmode $fh;
my $sha = Digest::SHA1->new;
$sha->addfile($fh);
$english_crc = $sha->hexdigest;
$english_crc = substr($english_crc, 0, 2);
close $fh;
}
my $target_id = $i;
if($binary && !$target_id) {
@ -501,6 +514,9 @@ extern unsigned char *language_strings[];
/* this contains the concatenation of all strings, separated by \\0 chars */
extern const unsigned char core_language_builtin[];
/* this is a checksum of the english language file */
#define ENGLISH_LANG_CHECKSUM 0x$english_crc
#include "${prefix}_enum.h"
MOO
@ -604,13 +620,13 @@ elsif($binary || $binvoice) {
if($binary) {
open(OUTF, ">$binary") or die "Error: Can't create $binary";
binmode OUTF;
printf OUTF ("%c%c%c%c", $LANGUAGE_COOKIE, $LANGUAGE_VERSION, $target_id,
$langoptions); # magic lang file header
printf OUTF ("%c%c%c%c%c", $LANGUAGE_COOKIE, $LANGUAGE_VERSION, $target_id,
$langoptions, hex($english_crc)); # magic lang file header
}
if($binvoice) {
open(OUTV, ">$binvoice") or die "Error: Can't create $binary";
binmode OUTV;
printf OUTV ("%c%c%c%c", $VOICE_COOKIE, $LANGUAGE_VERSION, $target_id,
printf OUTV ("%c%c%c%c", $VOICE_COOKIE, $VOICE_VERSION, $target_id,
$langoptions); # magic lang file header
}