From patchwork Thu Apr 28 20:55:07 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 66931 Delivered-To: patch@linaro.org Received: by 10.140.93.198 with SMTP id d64csp431377qge; Thu, 28 Apr 2016 13:55:43 -0700 (PDT) X-Received: by 10.98.93.5 with SMTP id r5mr23322181pfb.15.1461876943736; Thu, 28 Apr 2016 13:55:43 -0700 (PDT) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id k86si11994438pfj.248.2016.04.28.13.55.43 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 28 Apr 2016 13:55:43 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-return-69252-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org; spf=pass (google.com: domain of libc-alpha-return-69252-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=libc-alpha-return-69252-patch=linaro.org@sourceware.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id; q=dns; s= default; b=Br1o0KAsReaOw9FSBapSCHKXsn9RHaYtiTi0+hwxFNK4mLO+NZVT4 J78IWMj+MtkmCsm/Xv8gzCGgtLSnekAiuq0wdW5SsBc14gRJ5pK6HlYDSC7o+ZsC QX8HXcK954/ftMcZBuqafrEeTNTT7t2+jJTPzfCYuhrwyqXup1su1c= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id; s=default; bh=siJf0QBw5wWrnwwfT1L4NMgGOis=; b=MHXwDbJkWTAWHLQAIQvO8ToqQcjy KWDKHuaKDF0ZBxazR9YXtQulfQuRRZG3fycnzL4PiFyCjpenpbD6DazFAuvMYL/d NczDlzPLwqBOuknjP6nYsqRUV0UeC297JgKRfC09lt88BgP8lRM+WD0G4B0RehmO IW+Ete4j9toF+Eg= Received: (qmail 100887 invoked by alias); 28 Apr 2016 20:55:34 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 100871 invoked by uid 89); 28 Apr 2016 20:55:33 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=appending, 7028, states X-HELO: mail-yw0-f178.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id; bh=ZEZx5U+KXdJeqkNnIVafj5IroDwKOc7lByGuoeo0oqg=; b=gHckjs7a2zxiSjL2X2cbzpOe1DEQ8ci26BJRhbYPRWB76TamCeMucYoFA5PglG91gn /EVYqV4u9vLkh1bNl8H/WFehXtYR5jnh5vcJUGmObUYwDg9q2EmWfa9/V7wzL6MRobtl Xy35fBqGarLCvQHesI9JUJhqwuqQybS0fgoRRVAPxBuqq6lG81GooKeobbAY953qnCG7 qTf6+817BxD3VztinHUWsTAbKV9Q8dh0GM+zIbfRp38Aza2fYGG33j0Q7Xm41t4kjvTZ juzq25NN2EDL5EGC/pBzz0vdIamb+5es634VOis0LZRmf7eurPvid6WTnom1hr1jlkCQ EHFA== X-Gm-Message-State: AOPr4FVJbscMunMhkC8iFOibmJMh/V33f8Z2/2C9QhRrj2ke560gvZ4ZDoCWm07JGdljB6o1 X-Received: by 10.129.4.216 with SMTP id 207mr10449775ywe.184.1461876921403; Thu, 28 Apr 2016 13:55:21 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH v2] libio: Fix fmemopen append mode failure (BZ# 20005) Date: Thu, 28 Apr 2016 17:55:07 -0300 Message-Id: <1461876907-13655-1-git-send-email-adhemerval.zanella@linaro.org> This is an updated version on previous patch that fixes an issue regarding final '\0' that differs between writing and appending mode. For writing mode POSIX states null byte shall be written at the current position or at the end of the buffer, while for append a null byte shall be written at the end of the buffer if it fits. The implementation takes now in consideration by adding the final '\0' in append mode iff there is room for it. If noone opposes I will commit it by the end of the week. -- The fmemopen implementation does not account the file position correctly in append mode. The following example shows the failure: --- int main () { char buf[10] = "test"; FILE *fp = fmemopen (buf, 10, "a+"); fseek (fp, 0, SEEK_SET); int gr; if ((gr = getc (fp)) != 't' || (gr = getc (fp)) != 'e' || (gr = getc (fp)) != 's' || (gr = getc (fp)) != 't' || (gr = getc (fp)) != EOF) { printf ("%s: getc failed returned %i\n", __FUNCTION__, gr); return 1; } return 0; } --- This is due both how read and write operation update the buffer position, taking in consideration buffer lenght instead of maximum position defined by the open mode. This patch fixes it and also fixes fseek not returning EINVAL for invalid whence modes. Tested on x86_64 and i686. [BZ #20012] * libio/fmemopen.c (fmemopen_read): Use buffer maximum position, not length to calculate the buffer to read. (fmemopen_write): Set the buffer position based on bytes written. (fmemopen_seek): Return EINVAL for invalid whence modes. --- ChangeLog | 8 +++ libio/fmemopen.c | 28 +++++----- stdio-common/tst-fmemopen3.c | 118 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 140 insertions(+), 14 deletions(-) -- 2.7.4 diff --git a/ChangeLog b/ChangeLog index f1084ee..712be81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2016-04-27 Adhemerval Zanella + + [BZ #20012] + * libio/fmemopen.c (fmemopen_read): Use buffer maximum position, not + length to calculate the buffer to read. + (fmemopen_write): Set the buffer position based on bytes written. + (fmemopen_seek): Return EINVAL for invalid whence modes. + 2016-04-27 Florian Weimer [BZ #19831] diff --git a/libio/fmemopen.c b/libio/fmemopen.c index 9264b72..0f65590 100644 --- a/libio/fmemopen.c +++ b/libio/fmemopen.c @@ -50,16 +50,14 @@ fmemopen_read (void *cookie, char *b, size_t s) if (c->pos + s > c->maxpos) { - if ((size_t) c->pos == c->maxpos) - return 0; - s = c->size - c->pos; + s = c->maxpos - c->pos; + if ((size_t) c->pos > c->maxpos) + s = 0; } memcpy (b, &(c->buffer[c->pos]), s); c->pos += s; - if ((size_t) c->pos > c->maxpos) - c->maxpos = c->pos; return s; } @@ -70,28 +68,29 @@ fmemopen_write (void *cookie, const char *b, size_t s) { fmemopen_cookie_t *c = (fmemopen_cookie_t *) cookie;; _IO_off64_t pos = c->append ? c->maxpos : c->pos; - int addnullc; - - addnullc = (s == 0 || b[s - 1] != '\0'); + int addnullc = (s == 0 || b[s - 1] != '\0'); - if (pos + s + addnullc > c->size) + if (pos + s > c->size) { if ((size_t) (c->pos + addnullc) >= c->size) { __set_errno (ENOSPC); return 0; } - s = c->size - pos - addnullc; + s = c->size - pos; } memcpy (&(c->buffer[pos]), b, s); - c->pos += s; + c->pos = pos + s; if ((size_t) c->pos > c->maxpos) { c->maxpos = c->pos; - if (addnullc) + if (c->maxpos < c->size && addnullc) c->buffer[c->maxpos] = '\0'; + /* A null byte is written in a stream open for update iff it fits. */ + else if (c->append == 0 && addnullc != 0) + c->buffer[c->size-1] = '\0'; } return s; @@ -123,7 +122,10 @@ fmemopen_seek (void *cookie, _IO_off64_t *p, int w) } if (np < 0 || (size_t) np > c->size) - return -1; + { + __set_errno (EINVAL); + return -1; + } *p = c->pos = np; diff --git a/stdio-common/tst-fmemopen3.c b/stdio-common/tst-fmemopen3.c index 250f9ec..054b069 100644 --- a/stdio-common/tst-fmemopen3.c +++ b/stdio-common/tst-fmemopen3.c @@ -25,8 +25,13 @@ static void print_buffer (const char *s, size_t n) { size_t i; + printf ("{"); for (i=0; i