From b1a0467ffd656f7ec5c2c18677a7efcb989d4600 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Thu, 26 Jan 2023 03:56:19 +0800 Subject: [PATCH] fixes #21273; fixes an io.readLine off by one bug [backport 1.0] (#21276) fixes #21273; io.readLine off by one (cherry picked from commit c4d3d650baa88820dadeafa81ca75b6e495084f2) --- lib/system/io.nim | 7 ++++--- tests/stdlib/tio.nim | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/system/io.nim b/lib/system/io.nim index 2df5107ba4..f88ea80127 100644 --- a/lib/system/io.nim +++ b/lib/system/io.nim @@ -478,11 +478,12 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect], if last > 0 and line[last-1] == '\c': line.setLen(last-1) return last > 1 or fgetsSuccess - # We have to distinguish between two possible cases: + elif last > 0 and line[last-1] == '\0': + # We have to distinguish among three possible cases: # \0\l\0 => line ending in a null character. # \0\l\l => last line without newline, null was put there by fgets. - elif last > 0 and line[last-1] == '\0': - if last < pos + sp - 1 and line[last+1] != '\0': + # \0\l => last line without newline, null was put there by fgets. + if last >= pos + sp - 1 or line[last+1] != '\0': # bug #21273 dec last line.setLen(last) return last > 0 or fgetsSuccess diff --git a/tests/stdlib/tio.nim b/tests/stdlib/tio.nim index 0da64f9c26..fc1329c469 100644 --- a/tests/stdlib/tio.nim +++ b/tests/stdlib/tio.nim @@ -35,3 +35,21 @@ block: # readChars break doAssert n2s == @[2,2,2,1,0] doAssert s2 == s + + +import std/strutils + +block: # bug #21273 + let FILE = buildDir / "D20220119T134305.txt" + + let hex = "313632313920313632343720313632353920313632363020313632393020323035363520323037323120323131353020323239393820323331303520323332313020323332343820323332363820" + + + writeFile FILE, parseHexStr(hex) + + doAssert readFile(FILE).toHex == hex + + let f = open(FILE) + var s = newString(80) + while f.readLine(s): + doAssert s.toHex == hex