apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefan Fuhrmann <stefan.fuhrm...@wandisco.com>
Subject [PATCH] Fix apr_file_trunc for buffered files on Unix
Date Sun, 29 Jun 2014 10:52:49 GMT
The current Unix implementation of apr_file_trunk()
has a number of issues due to incompletely updating
the buffer state. Note that this is different from the
delayed flush() issue fixed in r1044440.

The following code snippet demonstrates the two
problems, one being access to stale data and the
other being the reported current read position being
wrong:

  apr_file_t *file;
  apr_size_t count;
  apr_off_t offset;
  char buffer[11];

  /* Issue 1: File read buffer does not get truncated. */
  apr_file_open(&file, "demo",
                APR_READ | APR_WRITE | APR_BUFFERED | APR_CREATE,
                APR_OS_DEFAULT, pool);

  count = 11;
  apr_file_write(file, "Hello World", &count);
  apr_file_flush(file);
  offset = 0;
  apr_file_seek(file, APR_SET, &offset);
  apr_file_read(file, buffer, &count);
  apr_file_trunc(file, 5);

  /* Attempting to read data should return nothing but it returns old data.
*/
  count = 6;
  buffer[0] = 0;
  apr_file_read(file, buffer, &count);
  apr_file_close(file);
  assert(count == 0 && buffer[0] == 0);

  /* Issue 2: File read buffer state is inconsistent. */
  apr_file_open(&file, "demo",
                APR_READ | APR_WRITE | APR_BUFFERED | APR_TRUNCATE,
                APR_OS_DEFAULT, pool);

  count = 11;
  apr_file_write(file, "Hello World", &count);
  apr_file_flush(file);
  offset = 0;
  apr_file_seek(file, APR_SET, &offset);
  apr_file_read(file, buffer, &count);
  apr_file_trunc(file, 5);

  /* Superficially, seek seems to work.. */
  offset = 0;
  apr_file_seek(file, APR_CUR, &offset);
  assert(offset == 5);

  /* .. but the internal buffer state is inconsistent making it fail later.
*/
  count = 1;
  apr_file_write(file, "X", &count);
  offset = 0;
  apr_file_seek(file, APR_CUR, &offset);
  apr_file_close(file);
  assert(offset == 6);

I attached a patch against /trunk.

-- Stefan^2.

[[[
Prevent stale buffer data and bogus file pointers to be returned
after apr_file_flush() on Unix.

* file_io/unix/seek.c
  (apr_file_trunc): Limit the data buffer to what will remain
                    beyond EOF after trunc(). If the trunc()
                    fails, having shortended buffer contents
                    does not effect the result of any APR call.

Patch by: stefan2
]]]

Mime
View raw message