aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-10-02 08:50:57 +0000
committerWerner Koch <[email protected]>2014-10-02 08:50:57 +0000
commit74abfcf0c3ba7cd6ce36540c70699fc1719248b3 (patch)
treea3f9a8691928cab61fe793c1ae325506b37c3122
parentGNU calls little-endian powerpc64 powerpc64le, not powerpc64el (diff)
downloadlibgpg-error-74abfcf0c3ba7cd6ce36540c70699fc1719248b3.tar.gz
libgpg-error-74abfcf0c3ba7cd6ce36540c70699fc1719248b3.zip
Add GPG_ERR_BOGUS_STRING and an experimental gpgrt_pending.
* src/visibility.c (gpgrt_pending, gpgrt_pending_unlocked): New. * src/estream.c (_gpgrt_pending, _gpgrt_pending_unlocked): New. (check_pending): new. (check_pending_fbf, check_pending_nbf): New. (es_func_mem_read, es_func_fd_read, es_func_w32_read) (es_func_fp_read, es_fill): Take care of the special 0 value for SIZE.
-rw-r--r--NEWS3
-rw-r--r--doc/errorref.txt22
-rw-r--r--src/err-codes.h.in4
-rw-r--r--src/estream.c111
-rw-r--r--src/gpg-error.def.in3
-rw-r--r--src/gpg-error.h.in4
-rw-r--r--src/gpg-error.vers2
-rw-r--r--src/gpgrt-int.h2
-rw-r--r--src/visibility.c12
-rw-r--r--src/visibility.h4
10 files changed, 160 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index 2e49b0c..4330408 100644
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,9 @@ Noteworthy changes in version 1.17 (unreleased) [C12/A12/R_]
GPG_ERR_BAD_HS_FINISHED NEW.
GPG_ERR_BAD_HS_SERVER_KEX NEW.
GPG_ERR_BAD_HS_CLIENT_KEX NEW.
+ GPG_ERR_BOGUS_STRING NEW.
+ gpgrt_pending NEW.
+ gpgrt_pending_unlocked NEW.
Noteworthy changes in version 1.16 (2014-09-18) [C12/A12/R2]
diff --git a/doc/errorref.txt b/doc/errorref.txt
index 666dca6..07b7cd4 100644
--- a/doc/errorref.txt
+++ b/doc/errorref.txt
@@ -219,7 +219,12 @@ GPG_ERR_INV_ARG Invalid argument
52 GPG_ERR_NOT_PROCESSED Data not processed
53 GPG_ERR_UNUSABLE_PUBKEY Unusable public key
54 GPG_ERR_UNUSABLE_SECKEY Unusable secret key
-55 GPG_ERR_INV_VALUE Invalid value
+
+GPG_ERR_INV_VALUE Invalid value
+
+ NTBTLS: - A DH parameter is out of range
+
+
56 GPG_ERR_BAD_CERT_CHAIN Bad certificate chain
GPG_ERR_MISSING_CERT Missing certificate
@@ -516,7 +521,13 @@ GPG_ERR_LIMIT_REACHED Limit reached
GnuPG: gpgtar: Extract directory can't be created because too
many of directories with a similar name are already existing.
-184 GPG_ERR_NOT_INITIALIZED Not initialized
+GPG_ERR_NOT_INITIALIZED Not initialized
+
+ An operation can't be performed because something has not been
+ initialized. This might be a missing initialization of an entire
+ subsystems or a prerequisite for using a function is not
+ fulfilled.
+
185 GPG_ERR_MISSING_ISSUER_CERT Missing issuer certificate
186 GPG_ERR_NO_KEYSERVER No keyserver available
@@ -699,6 +710,13 @@ GPG_ERR_BAD_HS_CLIENT_KEX Bad client key exchange message in handshake
NTBTLS: - As the description says.
+GPG_ERR_BOGUS_STRING Bogus string
+
+ Used if a protocol sends length prefixed strings which contain a
+ Nul byte and further processing would discard the rest of the
+ string. May also be used if a string contains unexpected and
+ possible dangerous characters (e.g. control characters in a domain
+ name).
GPG_ERR_KEY_DISABLED Key disabled
diff --git a/src/err-codes.h.in b/src/err-codes.h.in
index 9274530..704049c 100644
--- a/src/err-codes.h.in
+++ b/src/err-codes.h.in
@@ -273,8 +273,8 @@
247 GPG_ERR_BAD_HS_FINISHED Bad finished message in handshake
248 GPG_ERR_BAD_HS_SERVER_KEX Bad server key exchange message in handshake
249 GPG_ERR_BAD_HS_CLIENT_KEX Bad client key exchange message in handshake
-
-# 250 and 251 are free to be used.
+250 GPG_ERR_BOGUS_STRING Bogus string
+# 251 is free to be used.
252 GPG_ERR_KEY_DISABLED Key disabled
253 GPG_ERR_KEY_ON_CARD Not possible with a card based key
diff --git a/src/estream.c b/src/estream.c
index 46be363..2537141 100644
--- a/src/estream.c
+++ b/src/estream.c
@@ -625,6 +625,9 @@ es_func_mem_read (void *cookie, void *buffer, size_t size)
estream_cookie_mem_t mem_cookie = cookie;
gpgrt_ssize_t ret;
+ if (!size) /* Just the pending data check. */
+ return (mem_cookie->data_len - mem_cookie->offset)? 0 : -1;
+
if (size > mem_cookie->data_len - mem_cookie->offset)
size = mem_cookie->data_len - mem_cookie->offset;
@@ -898,7 +901,9 @@ es_func_fd_read (void *cookie, void *buffer, size_t size)
estream_cookie_fd_t file_cookie = cookie;
gpgrt_ssize_t bytes_read;
- if (IS_INVALID_FD (file_cookie->fd))
+ if (!size)
+ bytes_read = -1; /* We don't know whether anything is pending. */
+ else if (IS_INVALID_FD (file_cookie->fd))
{
_gpgrt_yield ();
bytes_read = 0;
@@ -1057,7 +1062,9 @@ es_func_w32_read (void *cookie, void *buffer, size_t size)
estream_cookie_w32_t w32_cookie = cookie;
gpgrt_ssize_t bytes_read;
- if (w32_cookie->hd == INVALID_HANDLE_VALUE)
+ if (!size)
+ bytes_to_read = -1; /* We don't know whether anything is pending. */
+ else if (w32_cookie->hd == INVALID_HANDLE_VALUE)
{
_gpgrt_yield ();
bytes_read = 0;
@@ -1273,6 +1280,9 @@ es_func_fp_read (void *cookie, void *buffer, size_t size)
estream_cookie_fp_t file_cookie = cookie;
gpgrt_ssize_t bytes_read;
+ if (!size)
+ return -1; /* We don't know whether anything is pending. */
+
if (file_cookie->fp)
{
if (pre_syscall_func)
@@ -1602,6 +1612,8 @@ es_fill (estream_t stream)
_set_errno (EOPNOTSUPP);
err = -1;
}
+ else if (!stream->buffer_size)
+ err = 0;
else
{
gpgrt_cookie_read_function_t func_read = stream->intern->func_read;
@@ -1937,6 +1949,18 @@ es_read_nbf (estream_t _GPGRT__RESTRICT stream,
return err;
}
+static int
+check_pending_nbf (estream_t _GPGRT__RESTRICT stream)
+{
+ gpgrt_cookie_read_function_t func_read = stream->intern->func_read;
+ char buffer[1];
+
+ if (!(*func_read) (stream->intern->cookie, buffer, 0))
+ return 1; /* Pending bytes. */
+ return 0; /* No pending bytes or error. */
+}
+
+
/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER in
fully-buffered-mode, storing the amount of bytes read in
*BYTES_READ. */
@@ -1987,6 +2011,26 @@ es_read_fbf (estream_t _GPGRT__RESTRICT stream,
return err;
}
+
+static int
+check_pending_fbf (estream_t _GPGRT__RESTRICT stream)
+{
+ gpgrt_cookie_read_function_t func_read = stream->intern->func_read;
+ char buffer[1];
+
+ if (stream->data_offset == stream->data_len)
+ {
+ /* Nothing more to read in current container, check whetehr it
+ would be possible to fill the container with new data. */
+ if (!(*func_read) (stream->intern->cookie, buffer, 0))
+ return 1; /* Pending bytes. */
+ }
+ else
+ return 1;
+ return 0;
+}
+
+
/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER in
line-buffered-mode, storing the amount of bytes read in
*BYTES_READ. */
@@ -2003,7 +2047,7 @@ es_read_lbf (estream_t _GPGRT__RESTRICT stream,
}
/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER, storing
- *the amount of bytes read in BYTES_READ. */
+ the amount of bytes read in BYTES_READ. */
static int
es_readn (estream_t _GPGRT__RESTRICT stream,
void *_GPGRT__RESTRICT buffer_arg,
@@ -2062,6 +2106,39 @@ es_readn (estream_t _GPGRT__RESTRICT stream,
return err;
}
+
+/* Return true if at least one byte is pending for read. This is a
+ best effort check and it it possible that bytes are still pending
+ even if false is returned. If the stream is in writing mode it is
+ switched to read mode. */
+static int
+check_pending (estream_t _GPGRT__RESTRICT stream)
+{
+ if (stream->flags.writing)
+ {
+ /* Switching to reading mode -> flush output. */
+ if (es_flush (stream))
+ return 0; /* Better return 0 on error. */
+ stream->flags.writing = 0;
+ }
+
+ /* Check unread data first. */
+ if (stream->unread_data_len)
+ return 1;
+
+ switch (stream->intern->strategy)
+ {
+ case _IONBF:
+ return check_pending_nbf (stream);
+ case _IOLBF:
+ case _IOFBF:
+ return check_pending_fbf (stream);
+ }
+
+ return 0;
+}
+
+
/* Try to unread DATA_N bytes from DATA into STREAM, storing the
amount of bytes successfully unread in *BYTES_UNREAD. */
static void
@@ -3394,6 +3471,34 @@ _gpgrt_syshd (estream_t stream, es_syshd_t *syshd)
int
+_gpgrt_pending_unlocked (estream_t stream)
+{
+ return check_pending (stream);
+}
+
+
+/* Return true if there is at least one byte pending for read on
+ STREAM. This does only work if the backend supports checking for
+ pending bytes and is thus mostly useful with cookie based backends.
+
+ Note that if this function is used with cookie based functions, the
+ read cookie may be called with 0 for the SIZE argument. If bytes
+ are pending the function is expected to return -1 in this case and
+ thus deviates from the standard behavior of read(2). */
+int
+_gpgrt_pending (estream_t stream)
+{
+ int ret;
+
+ lock_stream (stream);
+ ret = _gpgrt_pending_unlocked (stream);
+ unlock_stream (stream);
+
+ return ret;
+}
+
+
+int
_gpgrt_feof_unlocked (estream_t stream)
{
return es_get_indicator (stream, 0, 1);
diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in
index ac20a69..f17522e 100644
--- a/src/gpg-error.def.in
+++ b/src/gpg-error.def.in
@@ -137,4 +137,7 @@ EXPORTS
gpg_err_deinit @102
gpgrt_set_alloc_func @103
+ gpgrt_pending @104
+ gpgrt_pending_unlocked @105
+
;; end of file with public symbols for Windows.
diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in
index 80ce391..6ac6e0a 100644
--- a/src/gpg-error.h.in
+++ b/src/gpg-error.h.in
@@ -496,6 +496,8 @@ int gpgrt_ferror (gpgrt_stream_t stream);
int gpgrt_ferror_unlocked (gpgrt_stream_t stream);
void gpgrt_clearerr (gpgrt_stream_t stream);
void gpgrt_clearerr_unlocked (gpgrt_stream_t stream);
+int gpgrt_pending (gpgrt_stream_t stream);
+int gpgrt_pending_unlocked (gpgrt_stream_t stream);
int gpgrt_fflush (gpgrt_stream_t stream);
int gpgrt_fseek (gpgrt_stream_t stream, long int offset, int whence);
@@ -648,6 +650,8 @@ int gpgrt_vsnprintf (char *buf,size_t bufsize,
# define es_ferror_unlocked gpgrt_ferror_unlocked
# define es_clearerr gpgrt_clearerr
# define es_clearerr_unlocked gpgrt_clearerr_unlocked
+# define es_pending gpgrt_pending
+# define es_pending_unlocked gpgrt_pending_unlocked
# define es_fflush gpgrt_fflush
# define es_fseek gpgrt_fseek
# define es_fseeko gpgrt_fseeko
diff --git a/src/gpg-error.vers b/src/gpg-error.vers
index 43becea..c0e599a 100644
--- a/src/gpg-error.vers
+++ b/src/gpg-error.vers
@@ -64,6 +64,8 @@ GPG_ERROR_1.0 {
gpgrt_flockfile;
gpgrt_ftrylockfile;
gpgrt_funlockfile;
+ gpgrt_pending;
+ gpgrt_pending_unlocked;
gpgrt_feof;
gpgrt_feof_unlocked;
gpgrt_ferror;
diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h
index f97166f..8907835 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -102,6 +102,8 @@ int _gpgrt_ferror (gpgrt_stream_t stream);
int _gpgrt_ferror_unlocked (gpgrt_stream_t stream);
void _gpgrt_clearerr (gpgrt_stream_t stream);
void _gpgrt_clearerr_unlocked (gpgrt_stream_t stream);
+int _gpgrt_pending (gpgrt_stream_t stream);
+int _gpgrt_pending_unlocked (gpgrt_stream_t stream);
int _gpgrt_fflush (gpgrt_stream_t stream);
int _gpgrt_fseek (gpgrt_stream_t stream, long int offset, int whence);
diff --git a/src/visibility.c b/src/visibility.c
index f0d7fd1..f26f58c 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -298,6 +298,18 @@ gpgrt_funlockfile (estream_t stream)
}
int
+gpgrt_pending (estream_t stream)
+{
+ return _gpgrt_pending (stream);
+}
+
+int
+gpgrt_pending_unlocked (estream_t stream)
+{
+ return _gpgrt_pending_unlocked (stream);
+}
+
+int
gpgrt_feof (estream_t stream)
{
return _gpgrt_feof (stream);
diff --git a/src/visibility.h b/src/visibility.h
index feeb8d1..35878d7 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -87,6 +87,8 @@ MARK_VISIBLE (_gpgrt_get_std_stream)
MARK_VISIBLE (gpgrt_flockfile)
MARK_VISIBLE (gpgrt_ftrylockfile)
MARK_VISIBLE (gpgrt_funlockfile)
+MARK_VISIBLE (gpgrt_pending)
+MARK_VISIBLE (gpgrt_pending_unlocked)
MARK_VISIBLE (gpgrt_feof)
MARK_VISIBLE (gpgrt_feof_unlocked)
MARK_VISIBLE (gpgrt_ferror)
@@ -190,6 +192,8 @@ MARK_VISIBLE (gpgrt_set_alloc_func)
#define gpgrt_flockfile _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_ftrylockfile _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_funlockfile _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_pending _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_pending_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_feof _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_feof_unlocked _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_ferror _gpgrt_USE_UNDERSCORED_FUNCTION