Index: common/str.c
===================================================================
--- common/str.c	(revision 45adeeb6f146353989d5501fff8cf3e780e5dbea)
+++ common/str.c	(revision 23d4e6aeb10c07b0fc1436805639ab2e50cf7514)
@@ -547,4 +547,11 @@
 
 	for (; n > 0 && b[0]; b++, n--) {
+		if (b[0] < ' ') {
+			/* C0 control codes */
+			b[0] = replacement;
+			count++;
+			continue;
+		}
+
 		int cont = _continuation_bytes(b[0]);
 		if (__builtin_expect(cont, 0) == 0)
@@ -584,4 +591,11 @@
 		}
 
+		bool c1_control = (b[0] == 0b11000010 && b[1] < 0b10100000);
+		if (cont == 1 && c1_control) {
+			b[0] = replacement;
+			count++;
+			continue;
+		}
+
 		/* 0b1110!!!! 0b10!xxxxx 0b10xxxxxx */
 		if (cont == 2 && !(b[0] & 0b00001111) && !(b[1] & 0b00100000)) {
@@ -619,4 +633,8 @@
 }
 
+/** Replaces any byte that's not part of a complete valid UTF-8 character
+ * encoding with a replacement byte.
+ * Also replaces C0 and C1 control codes.
+ */
 size_t str_sanitize(char *str, size_t n, uint8_t replacement)
 {
