| From: | Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com> |
|---|---|
| To: | Evgeniy Gorbanyov <esgor(at)altlinux(dot)org> |
| Cc: | pgsql-hackers(at)lists(dot)postgresql(dot)org |
| Subject: | Re: Distinguish EOF from a read error when loading the relcache init file |
| Date: | 2026-11-13 02:20:57 |
| Message-ID: | E3F860B2-C8F9-4A5E-8CD9-AA2A60538E01@gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
> On Nov 11, 2026, at 17:04, Evgeniy Gorbanyov <esgor(at)altlinux(dot)org> wrote:
>
> Hi,
>
> load_relcache_init_file() treats a zero-length fread() of the next
> relation descriptor length as the end of pg_internal.init, which has
> no record count. fread() also returns zero when a read error
> transfers no data. In that case the file is accepted whenever the
> nailed rel and index counts already match, so a partial cache can be
> installed instead of bootstrapping it from the built-in descriptors.
>
> Check ferror() before treating a zero-length read as the end of the
> file.
>
> The patch is attached.
>
> Regards,
> Evgeniy Gorbanyov <0001-Distinguish-EOF-from-a-read-error-when-loading-the-r.patch>
```
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -6329,7 +6329,7 @@ load_relcache_init_file(bool shared)
nread = fread(&len, 1, sizeof(len), fp);
if (nread != sizeof(len))
{
- if (nread == 0)
+ if (nread == 0 && !ferror(fp))
break; /* end of file */
goto read_failed;
}
```
From the comment "/* end of file */" and the subsequent "goto read_failed" statement, it looks like this code intentionally distinguishes a normal EOF from a read failure. It also treats a partial read as a failure, which could indicate file corruption or truncation.
When no bytes are read, checking ferror(fp) or feof(fp) is necessary to distinguish a normal EOF from a read error. Otherwise, a read error could be silently treated as EOF.
Specific to this call site, without the patch, if an IO error happens to occur while reading no bytes, load_relcache_init_file() could incorrectly return true, even though the initialization file was not fully read.
I also searched the source tree for other fread() call sites, and this seems to be the only one missing an ferror() check.
So, this patch looks good to me. Since this code has been around for a long time, I think it's worth back-patching to all supported branches.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
| From | Date | Subject | |
|---|---|---|---|
| Next Message | JoongHyuk Shin | 2026-11-13 02:50:32 | Re: Deadlock detector fails to activate on a hot standby replica |
| Previous Message | Henson Choi | 2026-11-13 02:20:39 | Re: Row pattern recognition |