This is an archive of the discontinued Mercurial Phabricator instance.

cleanup: always `seek(0, io.SEEK_END)` after open in append mode before tell()
AbandonedPublic

Authored by durin42 on Jun 20 2019, 2:29 PM.

Details

Reviewers
None
Group Reviewers
hg-reviewers
Summary

Consider the program:

#include <stdio.h>

int main() {
  FILE *f = fopen("narf", "w");
  fprintf(f, "narf\n");
  fclose(f);

  f = fopen("narf", "a");
  printf("%ld\n", ftell(f));
  fprintf(f, "troz\n");
  printf("%ld\n", ftell(f));

  return 0;
}

on macOS, FreeBSD, and Linux with glibc, this program prints

5
10

but on musl libc (Alpine Linux and probably others) this prints

0
10

By my reading of
https://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html
this is technically correct, specifically:

Opening a file with append mode (a as the first character in the
mode argument) shall cause all subsequent writes to the file to be
forced to the then current end-of-file, regardless of intervening
calls to fseek().

in other words, the file position doesn't really matter in append-mode
files, and we can't depend on it being at all meaningful unless we
perform a seek() before tell() after open(..., 'a'). Experimentally
after a .write() we can do a .tell() and it'll always be reasonable,
but I'm unclear from reading the specification if that's a smart thing
to rely on.

These callsites were identified by applying the next changeset and
then fixing new crashes.

Diff Detail

Repository
rHG Mercurial
Lint
Lint Skipped
Unit
Unit Tests Skipped

Event Timeline

durin42 created this revision.Jun 20 2019, 2:29 PM

Note that I mailed a version to the list for stable. This doesn't quite cleanly apply there, so I made the change twice so I could write the next change without waiting for a merge.

durin42 abandoned this revision.Jul 8 2019, 1:15 PM