NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/59197: file descriptor seek -> read -> write causes file pos inconsistency



>Number:         59197
>Category:       kern
>Synopsis:       file descriptor seek -> read -> write causes file pos inconsistency
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Mar 19 12:45:00 +0000 2025
>Originator:     Rett Berg
>Release:        NetBSD 10.1
>Organization:
civboot.org
>Environment:
NetBSD rettbsd.lan 10.1 NetBSD 10.1 (GENERIC) #0: Mon Dec 16 13:08:11 UTC 2024  mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/amd64/compile/GENERIC amd64
>Description:
See "how to repeat"

Note that the following equivalent C code does NOT fail. I'm going to try again with FILE objects, which I think is what lua uses

```c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <errno.h>

int fd;
char buf[16];

void fw(const char* s) {
  int len = strlen(s);
  errno = 0;
  int w = write(fd, s, len);
  assert(len == w);
}
char* fr(const int n, const char* expect)   {
  assert(n == read(fd, buf, n));
  buf[n] = 0;
  assert(0 == strcmp(expect, buf));
}
void fs(const int n) {
  assert(n == lseek(fd, n, SEEK_SET));
}

int main() {
  int pos;
  printf("Started fd.c\n");
  fd = open("fd.c.txt", O_RDWR | O_CREAT | O_TRUNC);
  assert(fd > 0);
  // pos = lseek(fd, 0, SEEK_CUR);
  // assert(0 == pos);

  fw("11"); fw("22"); fw("33");
  pos = lseek(fd, 0, SEEK_CUR);
  assert(6 == pos);
  fs(0); fr(2, "11");
         fr(2, "22");
         fr(2, "33");
  fs(0); fr(2, "11");
  fw("20");
  pos = lseek(fd, 0, SEEK_CUR);
  printf("pos=%i\n", pos);
  assert(4 == pos);

  printf("fd.c Done\n");
  close(fd);
}
```
>How-To-Repeat:
-- file descriptor bug reproduction in lua 5.4

local f = io.open('/tmp/fd.txt', 'w+')

print('Test abcdef')
f:write'abcdef' -- len=6
f:seek'set'
assert('abcdef' == f:read(6))

f:seek('set', 1); f:write'ghi' -- replace 'bcd'
assert('ef' == f:read'a')
f:seek('set', 0); assert('aghief' == f:read'a')
f:close()

print('Test repo')
local f = io.open('/tmp/repo.txt', 'w+')

local function fr(...) return assert(f:read(...))  end
local function fw(...) return assert(f:write(...)) end
local function fs(pos) return assert(f:seek('set', pos)) end

fw'11'; fw'22'; fw'33'; assert(6 == f:seek'cur')
fs(0); assert('11' == f:read(2))
       assert('22' == f:read(2))
       assert('33' == f:read(2))
fs(0); assert('11' == f:read(2))
fw'20'; 
local p = f:seek'cur'
print('pos', p); assert(4 == p)

f:close()
print'Done'

>Fix:





Home | Main Index | Thread Index | Old Index