Return-Path: X-Original-To: apmail-apr-dev-archive@www.apache.org Delivered-To: apmail-apr-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id CB1DF11643 for ; Sun, 29 Jun 2014 10:53:18 +0000 (UTC) Received: (qmail 47159 invoked by uid 500); 29 Jun 2014 10:53:17 -0000 Delivered-To: apmail-apr-dev-archive@apr.apache.org Received: (qmail 47076 invoked by uid 500); 29 Jun 2014 10:53:17 -0000 Mailing-List: contact dev-help@apr.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Id: Delivered-To: mailing list dev@apr.apache.org Received: (qmail 47065 invoked by uid 99); 29 Jun 2014 10:53:17 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 29 Jun 2014 10:53:17 +0000 X-ASF-Spam-Status: No, hits=1.5 required=5.0 tests=HTML_MESSAGE,RCVD_IN_DNSWL_LOW,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of stefan.fuhrmann@wandisco.com designates 209.85.223.176 as permitted sender) Received: from [209.85.223.176] (HELO mail-ie0-f176.google.com) (209.85.223.176) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 29 Jun 2014 10:53:14 +0000 Received: by mail-ie0-f176.google.com with SMTP id rd18so5694280iec.7 for ; Sun, 29 Jun 2014 03:52:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=wandisco.com; s=gapps; h=mime-version:date:message-id:subject:from:to:content-type; bh=GU5DhvnPQStN3GzWoefnToGbPwVLxOG0MZlJ83buQyM=; b=I6S9qhqCn3YtMFfTbQhFoIETI0h9lvreA27c5z1SWQ2rXRgTVoFljXsWqQiyCfKw72 8xCluP3qadsG67tG04AU4lvTG+9QNwXht2kCrQeT+c5RQXGnC30QvwzGRl2R7r/VhGvF W3wvvRPAjeK91LToDCb4QLuvg8UtuFyF29f84= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:date:message-id:subject:from:to :content-type; bh=GU5DhvnPQStN3GzWoefnToGbPwVLxOG0MZlJ83buQyM=; b=bkkmIQwcpKv3bZGGTV//nCqzPnK4zbk9MYrJaaA2rLGKPz2uWeEDXX5cfBZjuobgV2 vPhkUczhrHaIrwhBGizeeOTRG/CFNe+Z5n61MClCN5KyAKQnXlsTuuTn+bEV2ttkOYPh BdGoyZYaQjCfYOePpa/pdMXz7vVGZaqTXhRmsok7bnDtppSaoR5niBeS74duh+yEH9/2 UloMzmBdOS9aXCcHqvyu5hRGKpuoZzYHJGh9pNQow43/Le/mLrVB4QVmQkSa9B/8NsUW iw4VOfpjl+8uPp1ixle9T9K7mxKGymeQbYey8JvJDJlIxFeSqTpU6hGzjvYnqb5oEK3A /TsA== X-Gm-Message-State: ALoCoQnzbpkX1P01cOa/1hjT7kjOeucACx1GAY4f+MP8uhvkAWa0doXrlTzGx3rfRsioUSqu+8Fc MIME-Version: 1.0 X-Received: by 10.50.114.34 with SMTP id jd2mr24589066igb.35.1404039169140; Sun, 29 Jun 2014 03:52:49 -0700 (PDT) Received: by 10.50.231.131 with HTTP; Sun, 29 Jun 2014 03:52:49 -0700 (PDT) Date: Sun, 29 Jun 2014 12:52:49 +0200 Message-ID: Subject: [PATCH] Fix apr_file_trunc for buffered files on Unix From: Stefan Fuhrmann To: APR Developer List Content-Type: multipart/mixed; boundary=047d7b414118eda07904fcf757d5 X-Virus-Checked: Checked by ClamAV on apache.org --047d7b414118eda07904fcf757d5 Content-Type: multipart/alternative; boundary=047d7b414118eda07504fcf757d3 --047d7b414118eda07504fcf757d3 Content-Type: text/plain; charset=UTF-8 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 ]]] --047d7b414118eda07504fcf757d3 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
The current Unix implementation of apr_file= _trunk()
has a number of issues due to incompletely updating
th= e buffer state. Note that this is different from the
delayed flush() iss= ue 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:

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

=C2=A0 /* Issue 1: File read buffer does not get truncated. */<= br>=C2=A0 apr_file_open(&file, "demo",
=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 AP= R_READ | APR_WRITE | APR_BUFFERED | APR_CREATE,
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 APR_OS_DEFAULT, pool);

=C2=A0 count =3D 11;
=C2= =A0 apr_file_write(file, "Hello World", &count);
=C2=A0 ap= r_file_flush(file);
=C2=A0 offset =3D 0;
=C2=A0 apr_file_seek(file, A= PR_SET, &offset);
=C2=A0 apr_file_read(file, buffer, &count); =C2=A0 apr_file_trunc(file, 5);

=C2=A0 /* Attempting to read data sh= ould return nothing but it returns old data. */
=C2=A0 count =3D 6;
= =C2=A0 buffer[0] =3D 0;
=C2=A0 apr_file_read(file, buffer, &count);<= br>=C2=A0 apr_file_close(file);
=C2=A0 assert(count =3D=3D 0 && buffer[0] =3D=3D 0);

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

=C2=A0 count =3D 11;
=C2= =A0 apr_file_write(file, "Hello World", &count);
=C2=A0 ap= r_file_flush(file);
=C2=A0 offset =3D 0;
=C2=A0 apr_file_seek(file, A= PR_SET, &offset);
=C2=A0 apr_file_read(file, buffer, &count); =C2=A0 apr_file_trunc(file, 5);

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

=C2=A0 /* .. but t= he internal buffer state is inconsistent making it fail later. */
=C2=A0 count =3D 1;
=C2=A0 apr_file_write(file, "X", &coun= t);
=C2=A0 offset =3D 0;
=C2=A0 apr_file_seek(file, APR_CUR, &off= set);
=C2=A0 apr_file_close(file);
=C2=A0 assert(offset =3D=3D 6);
I attached a patch against /trunk.

-- Stefan^2.

[[[
Prevent stale buffer d= ata and bogus file pointers to be returned
after apr_file_flush() on Uni= x.

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

Patch by: stefan2
]]]
--047d7b414118eda07504fcf757d3-- --047d7b414118eda07904fcf757d5 Content-Type: text/x-patch; charset=US-ASCII; name="seek.patch" Content-Disposition: attachment; filename="seek.patch" Content-Transfer-Encoding: base64 X-Attachment-Id: f_hx08fg4x0 SW5kZXg6IGZpbGVfaW8vdW5peC9zZWVrLmMKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQotLS0gZmlsZV9pby91bml4L3Nl ZWsuYwkocmV2aXNpb24gMTYwNjQ0NikKKysrIGZpbGVfaW8vdW5peC9zZWVrLmMJKHdvcmtpbmcg Y29weSkKQEAgLTExNyw2ICsxMTcsMjQgQEAKICAgICAgICAgICAgIC8qIFJlc2V0IGJ1ZmZlciBw b3NpdGlvbnMgZm9yIHdyaXRlIG1vZGUgKi8KICAgICAgICAgICAgIGZwLT5idWZwb3MgPSBmcC0+ ZGlyZWN0aW9uID0gZnAtPmRhdGFSZWFkID0gMDsKICAgICAgICAgfQorCisgICAgICAgIC8qIExp bWl0IHRoZSBidWZmZXJlZCBkYXRhIHRvIHdoYXQgd2lsbCByZW1haW4gb2YgdGhlIGFjdHVhbCBm aWxlLgorICAgICAgICAgKiBUaGF0IHByZXZlbnRzIHN0YWxlIGRhdGEgZnJvbSBiZWluZyByZWFk IGFuZCB3cm9uZyBmaWxlIGxvY2F0aW9ucworICAgICAgICAgKiBiZWluZyByZXBvcnRlZC4gKi8K KyAgICAgICAgaWYgKGZwLT5maWxlUHRyID49IG9mZnNldCkgeworICAgICAgICAgICAgLyogVGhl IGVudGlyZSBidWZmZXIgd2lsbCBsaWUgYmV5b25kIEVPRiBub3cuIFB1dCBpdCBhdCBFT0YuICov CisgICAgICAgICAgICBmcC0+ZGF0YVJlYWQgPSBmcC0+YnVmcG9zID0gMDsKKyAgICAgICAgICAg IGZwLT5maWxlUHRyID0gb2Zmc2V0OworICAgICAgICB9CisgICAgICAgIGVsc2UgaWYgKGZwLT5m aWxlUHRyICsgZnAtPmRhdGFSZWFkID4gb2Zmc2V0KSB7CisgICAgICAgICAgICAvKiBPbmx5IHBh cnQgb2YgdGhlIGJ1ZmZlciB3aWxsIGJlIGJleW9uZCBFT0YuCisgICAgICAgICAgICAgKiBUcnVu Y2F0ZSBpdCBhbmQgYWRqdXN0IHRoZSByZWFkIHBvaW50ZXIgaWYgbmVjZXNzYXJ5LiAqLworICAg ICAgICAgICAgZnAtPmRhdGFSZWFkID0gb2Zmc2V0IC0gZnAtPmZpbGVQdHI7CisgICAgICAgICAg ICBpZiAoZnAtPmRhdGFSZWFkIDwgZnAtPmJ1ZnBvcykgeworICAgICAgICAgICAgICAgIGZwLT5i dWZwb3MgPSBmcC0+ZGF0YVJlYWQ7CisgICAgICAgICAgICB9CisgICAgICAgIH0KKwogICAgICAg ICBmaWxlX3VubG9jayhmcCk7CiAgICAgICAgIGlmIChyYykgewogICAgICAgICAgICAgcmV0dXJu IHJjOwo= --047d7b414118eda07904fcf757d5--