/* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */
uint8_t error_pkt[4 + 32];
struct passwd *pw;
- /* used in tftpd_main(), a bit big for stack: */
- char block_buf[TFTP_BLKSIZE_DEFAULT];
+ /* Used in tftpd_main() for initial packet */
+ /* Some HP PA-RISC firmware always sends fixed 516-byte requests */
+ char block_buf[516];
+ char block_buf_tail[1];
#if ENABLE_FEATURE_TFTP_PROGRESS_BAR
off_t pos;
off_t size;
#endif
} FIX_ALIASING;
#define G (*(struct globals*)&bb_common_bufsiz1)
-struct BUG_G_too_big {
- char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
-};
-#define INIT_G() do { } while (0)
+#define INIT_G() do { \
+ BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
+} while (0)
#define G_error_pkt_reason (G.error_pkt[3])
#define G_error_pkt_str ((char*)(G.error_pkt + 4))
* as if it is "block 0" */
block_nr = 0;
}
-
} else { /* tftp */
/* Open file (must be after changing user) */
local_fd = CMD_GET(option_mask32) ? STDOUT_FILENO : STDIN_FILENO;
xchroot(argv[0]);
}
- result = recv_from_to(STDIN_FILENO, G.block_buf, sizeof(G.block_buf),
+ result = recv_from_to(STDIN_FILENO,
+ G.block_buf, sizeof(G.block_buf) + 1,
+ /* ^^^ sizeof+1 to reliably detect oversized input */
0 /* flags */,
&peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len);
error_msg = "malformed packet";
opcode = ntohs(*(uint16_t*)G.block_buf);
- if (result < 4 || result >= sizeof(G.block_buf)
- || G.block_buf[result-1] != '\0'
+ if (result < 4 || result > sizeof(G.block_buf)
+ /*|| G.block_buf[result-1] != '\0' - bug compatibility, see below */
|| (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */
IF_GETPUT(&&)
IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
) {
goto err;
}
+ /* Some HP PA-RISC firmware always sends fixed 516-byte requests,
+ * with trailing garbage.
+ * Support that by not requiring NUL to be the last byte (see above).
+ * To make strXYZ() ops safe, force NUL termination:
+ */
+ G.block_buf_tail[0] = '\0';
+
local_file = G.block_buf + 2;
if (local_file[0] == '.' || strstr(local_file, "/.")) {
error_msg = "dot in file name";