From 013b91586950d50c98da1404b159dcfcf844a7f4 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Mon, 25 Jun 2018 04:18:30 +0200 Subject: [PATCH] af_alg: Fail in continuable manner on Linux/powerpc64le. Reported by Assaf Gordon in . * lib/af_alg.c (afalg_stream): On non-seekable streams, try a single- byte send() as the first round. --- ChangeLog | 8 ++++++++ lib/af_alg.c | 20 +++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 33da642c3b..d2f212874f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2018-06-24 Bruno Haible + + af_alg: Fail in continuable manner on Linux/powerpc64le. + Reported by Assaf Gordon + in . + * lib/af_alg.c (afalg_stream): On non-seekable streams, try a single- + byte send() as the first round. + 2018-06-24 Bruno Haible af_alg: Fix state of stream after sendfile() succeeds. diff --git a/lib/af_alg.c b/lib/af_alg.c index 2753ab9a42..549cdcfdde 100644 --- a/lib/af_alg.c +++ b/lib/af_alg.c @@ -157,7 +157,10 @@ afalg_stream (FILE *stream, const char *alg, for (;;) { char buf[BLOCKSIZE]; - ssize_t size = fread (buf, 1, sizeof buf, stream); + /* When the stream is not seekable, start with a single-byte block, + so that we can use ungetc() in the case that send() fails. */ + size_t blocksize = (nseek == 0 && off < 0 ? 1 : BLOCKSIZE); + ssize_t size = fread (buf, 1, blocksize, stream); if (size == 0) { /* On Linux < 4.9, the value for an empty stream is wrong (all 0). @@ -170,8 +173,18 @@ afalg_stream (FILE *stream, const char *alg, nseek -= size; if (send (ofd, buf, size, MSG_MORE) != size) { - result = (fseeko (stream, nseek, SEEK_CUR) == 0 - ? -EAFNOSUPPORT : -EIO); + if (nseek == -1) + { + /* 1 byte of pushback buffer is guaranteed on stream, even + if stream is not seekable. */ + ungetc ((unsigned char) buf[0], stream); + result = -EAFNOSUPPORT; + } + else if (fseeko (stream, nseek, SEEK_CUR) == 0) + /* The position of stream has been restored. */ + result = -EAFNOSUPPORT; + else + result = -EIO; break; } @@ -187,6 +200,7 @@ afalg_stream (FILE *stream, const char *alg, if (result == 0 && read (ofd, resblock, hashlen) != hashlen) { if (nseek == 0 || fseeko (stream, nseek, SEEK_CUR) == 0) + /* The position of stream has been restored. */ result = -EAFNOSUPPORT; else result = -EIO; -- 2.39.5