diff --git a/ChangeLog b/ChangeLog
index 996704135..5b0af2135 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2022-12-16  Oliver Kiddle  <opk@zsh.org>
 
+	* Jun T.: 51207: Src/builtin.c, Test/B04read.ztst:
+	fix for read -d when the delimiter is a byte >= 0x80
+
 	* 51212: Etc/zsh-development-guide, Src/Modules/curses.c,
 	Src/Modules/stat.c, Src/Modules/zftp.c, Src/Modules/zpty.c,
 	Src/Modules/zutil.c, Src/Zle/compcore.c, Src/Zle/complete.c,
diff --git a/Src/builtin.c b/Src/builtin.c
index db83313d6..951970138 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -6286,7 +6286,7 @@ bin_read(char *name, char **args, Options ops, UNUSED(int func))
     char *laststart;
     size_t ret;
 #else
-    char delim = '\n';
+    int delim = '\n';
 #endif
 
     if (OPT_HASARG(ops,c='k')) {
@@ -6413,10 +6413,11 @@ bin_read(char *name, char **args, Options ops, UNUSED(int func))
 	if (wi != WEOF)
 	    delim = (wchar_t)wi;
 	else
-	    delim = (wchar_t)((delimstr[0] == Meta) ?
+	    delim = (wchar_t) (unsigned char) ((delimstr[0] == Meta) ?
 			      delimstr[1] ^ 32 : delimstr[0]);
 #else
-        delim = (delimstr[0] == Meta) ? delimstr[1] ^ 32 : delimstr[0];
+        delim = (unsigned char) ((delimstr[0] == Meta) ?
+			delimstr[1] ^ 32 : delimstr[0]);
 #endif
 	if (SHTTY != -1) {
 	    struct ttyinfo ti;
diff --git a/Test/B04read.ztst b/Test/B04read.ztst
index 25c3d4173..96adf51c7 100644
--- a/Test/B04read.ztst
+++ b/Test/B04read.ztst
@@ -82,6 +82,12 @@
 >Testing the
 >null hypothesis
 
+ print -n $'first line\x80second line\x80' |
+ while read -d $'\x80' line; do print $line; done
+0:read with a delimiter >= 0x80
+>first line
+>second line
+
 # Note that trailing NULLs are not stripped even if they are in
 # $IFS; only whitespace characters contained in $IFS are stripped.
  print -n $'Aaargh, I hate nulls.\0\0\0' | read line