1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-11-20 02:42:09 +03:00

src: fix libssh2_store_*() for >u32 inputs

`_libssh2_store_str()` and `_libssh2_store_bignum2_bytes()` accept
inputs of `size_t` max, store the size as 32-bit unsigned integer, then
store the complete input buffer.

With inputs larger than `UINT_MAX` this means the stored size is smaller
than the data that follows it.

This patch truncates the stored data to the stored size, and now returns
a boolean with false if the stored length differs from the requested
one. Also add `assert()`s for this condition.

This is still not a correct fix, as we now dump consistent, but still
truncated data which is not what the caller wants. In future steps we'll
need to update all callers that might pass large data to this function
to check the return value and handle an error, or make sure to not call
this function with more than UINT_MAX bytes of data.

Ref: c3bcdd88a4 (2010-04-17)
Ref: ed439a29bb (2022-09-29)

Closes #1025
This commit is contained in:
Viktor Szakats
2023-05-03 21:17:01 +00:00
parent e36b21df91
commit ebf644fb6a
2 changed files with 31 additions and 17 deletions

View File

@@ -45,6 +45,7 @@
#endif
#include <errno.h>
#include <assert.h>
#ifdef WIN32
/* Force parameter type. */
@@ -254,37 +255,50 @@ void _libssh2_store_u32(unsigned char **buf, uint32_t value)
/* _libssh2_store_str
*/
void _libssh2_store_str(unsigned char **buf, const char *str, size_t len)
int _libssh2_store_str(unsigned char **buf, const char *str, size_t len)
{
_libssh2_store_u32(buf, (uint32_t)len);
if(len) {
memcpy(*buf, str, len);
*buf += len;
uint32_t len_stored = (uint32_t)len;
_libssh2_store_u32(buf, len_stored);
if(len_stored) {
memcpy(*buf, str, len_stored);
*buf += len_stored;
}
assert(len_stored == len);
return len_stored == len;
}
/* _libssh2_store_bignum2_bytes
*/
void _libssh2_store_bignum2_bytes(unsigned char **buf,
int _libssh2_store_bignum2_bytes(unsigned char **buf,
const unsigned char *bytes,
size_t len)
{
int extraByte = 0;
uint32_t len_stored;
uint32_t extraByte;
const unsigned char *p;
for(p = bytes; len > 0 && *p == 0; --len, ++p) {}
extraByte = (len > 0 && (p[0] & 0x80) != 0);
_libssh2_store_u32(buf, (uint32_t)(len + extraByte));
len_stored = (uint32_t)len;
if(extraByte && len_stored == 0xffffffff)
len_stored--;
_libssh2_store_u32(buf, len_stored + extraByte);
if(extraByte) {
*buf[0] = 0;
*buf += 1;
}
if(len > 0) {
memcpy(*buf, p, len);
*buf += len;
if(len_stored) {
memcpy(*buf, p, len_stored);
*buf += len_stored;
}
assert(len_stored == len);
return len_stored == len;
}
/* Base64 Conversion */

View File

@@ -108,8 +108,8 @@ uint32_t _libssh2_ntohu32(const unsigned char *buf);
libssh2_uint64_t _libssh2_ntohu64(const unsigned char *buf);
void _libssh2_htonu32(unsigned char *buf, uint32_t val);
void _libssh2_store_u32(unsigned char **buf, uint32_t value);
void _libssh2_store_str(unsigned char **buf, const char *str, size_t len);
void _libssh2_store_bignum2_bytes(unsigned char **buf,
int _libssh2_store_str(unsigned char **buf, const char *str, size_t len);
int _libssh2_store_bignum2_bytes(unsigned char **buf,
const unsigned char *bytes,
size_t len);
void *_libssh2_calloc(LIBSSH2_SESSION *session, size_t size);