summaryrefslogtreecommitdiff
path: root/libhw_cr/w5500.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-22 18:51:59 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-05-06 11:53:17 -0600
commit24e5d0ec1219e2dbb4b9510ef20833092a2b3871 (patch)
tree01bbcc34c6190fa1c35b2625e9ba1744b1447606 /libhw_cr/w5500.c
parentf09b7435b3a5222597d27238226d23ec0cbd5bd2 (diff)
wip: Build with -Wconversionlukeshu/safe-conversion
I think this found a real bug in the dhcp packet parser. I don't think anything called lib9p_str{,n}() values that could be big enough, but their bounds-checking was broken.
Diffstat (limited to 'libhw_cr/w5500.c')
-rw-r--r--libhw_cr/w5500.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/libhw_cr/w5500.c b/libhw_cr/w5500.c
index e676364..8ec3f4d 100644
--- a/libhw_cr/w5500.c
+++ b/libhw_cr/w5500.c
@@ -68,6 +68,10 @@
*/
#include <inttypes.h> /* for PRIu{n} */
+#include <limits.h> /* for SSIZE_MAX, not set by newlib */
+#ifndef SSIZE_MAX
+#define SSIZE_MAX (SIZE_MAX >> 1)
+#endif
/* TODO: Write a <libhw/generic/gpio.h> to avoid w5500.c being
* pico-sdk-specific. */
@@ -318,14 +322,15 @@ void _w5500_init(struct w5500 *chip,
#if CONFIG_W5500_VALIDATE_SPI
/* Validate that SPI works correctly. */
bool spi_ok = true;
- for (uint16_t a = 0; a < 0x100; a++) {
+ uint8_t a = 0;
+ do {
w5500ll_write_sock_reg(chip->spidev, 0, mode, a);
uint8_t b = w5500ll_read_sock_reg(chip->spidev, 0, mode);
if (b != a) {
log_errorf("SPI to W5500 does not appear to be functional: wrote:0x%02"PRIx16" != read:0x%02"PRIx8, a, b);
spi_ok = false;
}
- }
+ } while (a++ != 0xff);
if (!spi_ok)
__lm_abort();
w5500ll_write_sock_reg(chip->spidev, 0, mode, 0);
@@ -612,6 +617,7 @@ static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec
ASSERT_SELF(stream_conn, TCP);
if (count == 0)
return 0;
+ assert(count <= SSIZE_MAX);
/* What we really want is to pause until we receive an ACK for
* some data we just queued, so that we can line up some new
@@ -657,7 +663,7 @@ static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec
/* Queue data to be sent. */
if ((size_t)freesize > count-done)
- freesize = count-done;
+ freesize = (uint16_t)(count-done);
uint16_t ptr = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_write_pointer));
w5500ll_writev(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, TX), iov, iovcnt, done, freesize);
w5500ll_write_sock_reg(chip->spidev, socknum, tx_write_pointer, uint16be_marshal(ptr+freesize));
@@ -681,7 +687,8 @@ static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec
}
}
log_debugf(" => send finished");
- return done;
+ assert(done <= count); /* because we validated that count <= SSIZE_MAX */
+ return (ssize_t)done;
}
static void w5500_tcp_set_read_deadline(struct _w5500_socket *socket, uint64_t ns) {
@@ -759,7 +766,7 @@ static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec
uint16_t ptr = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, rx_read_pointer));
/* Read the data. */
if ((size_t)avail > count)
- avail = count;
+ avail = (uint16_t)count;
w5500ll_readv(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, RX), iov, iovcnt, avail);
/* Tell the chip that we read the data. */
w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, uint16be_marshal(ptr+avail));
@@ -807,18 +814,19 @@ static int w5500_tcp_close_write(struct _w5500_socket *socket) { return w5500_tc
/* udp_conn methods ***********************************************************/
-static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t count,
+static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t _count,
struct net_ip4_addr node, uint16_t port) {
log_debugf("udp_conn.sendto()");
ASSERT_SELF(packet_conn, UDP);
assert(buf);
- assert(count);
+ assert(_count);
uint16_t bufsize = ((uint16_t)w5500ll_read_sock_reg(chip->spidev, socknum, tx_buf_size))*1024;
- if (count > bufsize) {
+ if (_count > (size_t)bufsize) {
log_debugf(" => msg too large");
return -NET_EMSGSIZE;
}
+ uint16_t count = (uint16_t)_count;
for (;;) {
cr_mutex_lock(&chip->mu);
@@ -944,7 +952,7 @@ static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_
.iov_len = len,
}), 1, 0);
/* Tell the chip that we read the data. */
- w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, uint16be_marshal(ptr+8+len));
+ w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, uint16be_marshal((uint16_t)(ptr+len+8)));
w5500_socket_cmd(socket, CMD_RECV);
/* Return. */
LO_CALL(bootclock, del_trigger, &trigger);