Skip to content

Commit

Permalink
ftp: Fix corruption with segmented TCP packets
Browse files Browse the repository at this point in the history
Co-authored-by: Dustin Holden <[email protected]>
  • Loading branch information
Ryzee119 and LoveMHz committed Dec 14, 2023
1 parent c565c24 commit ccc740f
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 14 deletions.
8 changes: 3 additions & 5 deletions src/libs/ftpd/ftp_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,17 +407,15 @@ FRESULT ftps_f_close(FIL *fp)
return res;
}

FRESULT ftps_f_write(FIL *fp, const void *buffer, uint32_t buflen, uint32_t *written)
FRESULT ftps_f_write(FIL *fp, struct pbuf *p, uint32_t buflen, uint32_t *written)
{
HANDLE hfile = fp->h;
FRESULT res = FR_OK;

const uint8_t *prcvbuf = (const uint8_t *)buffer;
// Write the correct amount of bytes to fill up to FILE_CACHE_SIZE exactly.
int next_spot = fp->bytes_cached + buflen;
int len = (next_spot < FILE_CACHE_SIZE) ? buflen : (buflen - (next_spot - FILE_CACHE_SIZE));
memcpy(&fp->cache_buf[fp->cache_index][fp->bytes_cached], prcvbuf, len);
fp->bytes_cached += len;
fp->bytes_cached += pbuf_copy_partial(p, &fp->cache_buf[fp->cache_index][fp->bytes_cached], len, 0);

// If we have filled the file write cache, write it out.
assert(fp->bytes_cached <= FILE_CACHE_SIZE);
Expand All @@ -435,7 +433,7 @@ FRESULT ftps_f_write(FIL *fp, const void *buffer, uint32_t buflen, uint32_t *wri
assert(remaining >= 0);
if (remaining > 0)
{
memcpy(fp->cache_buf[fp->cache_index], &prcvbuf[len], remaining);
pbuf_copy_partial(p, &fp->cache_buf[fp->cache_index], remaining, len);
}
fp->bytes_cached = remaining;
}
Expand Down
2 changes: 1 addition & 1 deletion src/libs/ftpd/ftp_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ FRESULT ftps_f_unlink(const char *path);
FRESULT ftps_f_open(FIL *fp, const char *path, uint8_t mode);
size_t ftps_f_size(FIL *fp);
FRESULT ftps_f_close(FIL *fp);
FRESULT ftps_f_write(FIL *fp, const void *buffer, uint32_t len, uint32_t *written);
FRESULT ftps_f_write(FIL *fp, struct pbuf *p, uint32_t buflen, uint32_t *written);
FRESULT ftps_f_read(FIL *fp, void *buffer, uint32_t len, uint32_t *read, uint32_t position);
FRESULT ftps_f_mkdir(const char *path);
FRESULT ftps_f_rename(const char *from, const char *to);
Expand Down
12 changes: 4 additions & 8 deletions src/libs/ftpd/ftp_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1034,16 +1034,14 @@ static void ftp_cmd_stor(ftp_data_t *ftp)
ftp_send(ftp, "150 Connected to port %u\r\n", ftp->data_port);

//
struct pbuf *rcvbuf = NULL;
void *prcvbuf;
uint16_t buflen = 0;
struct pbuf *p = NULL;
int8_t file_err = 0;
int8_t con_err = 0;
uint32_t bytes_written = 0;
while (1)
{
// receive data from ftp client ok?
con_err = netconn_recv_tcp_pbuf(ftp->dataconn, &rcvbuf);
con_err = netconn_recv_tcp_pbuf(ftp->dataconn, &p);

// socket closed? (end of file)
if (con_err == ERR_CLSD)
Expand All @@ -1059,10 +1057,8 @@ static void ftp_cmd_stor(ftp_data_t *ftp)
}

// housekeeping
prcvbuf = rcvbuf->payload;
buflen = rcvbuf->tot_len;
file_err = ftps_f_write(&ftp->file, prcvbuf, buflen, (uint32_t *)&bytes_written);
pbuf_free(rcvbuf);
file_err = ftps_f_write(&ftp->file, p, p->tot_len, (uint32_t *)&bytes_written);
pbuf_free(p);

// error in nested loop?
if (file_err != FR_OK)
Expand Down

0 comments on commit ccc740f

Please sign in to comment.