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 Netto X-Patchwork-Id: 616414 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3qwpy45zN9z9sDX for ; Fri, 29 Apr 2016 06:55:40 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b=Uj3j1hjm; dkim-atps=neutral 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=Q30Ons6M3NTzt3/uoNGDvYS9i6mu3He4TaM947cN4V26AwHlaXtT5 bBnInI0FgELJhI6RWeNcFy+ZQUTNr2TFTqOwyQzq523PknyDui0MSAFY5YT6fo7f 3SfCuj2g1h51KcwmydROdGPKhqbwcFT9Btb9iHMWhHBG+/B8W8MV3w= 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=Uj3j1hjmVv8qZMogdHaHic4l3IsP dcP/aNv/wmdClqnf5YIEfXbnUstOAg22YEBPaWguSCZ2RJMMcz//gTHVG5WXe0xC ta93Bup65st5A1fdfNja1d/biYQvYpUCMtuqfygJUdYvnbm75UmZhsHOirabxTa7 bDcmhncd7OqeIgw= 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(-) 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