I would like to report a second current-head `Intra-Object Overflow` in `src/stream.c`, this time in the FTP/HTTP path parser used by `openftp()`.
This is again independent of the earlier `stropen(stream->path, path)` issue, because the total path can remain below `MAXSTRPATH` while one parsed component still exceeds the width of the embedded destination field.
The relevant current-head object layout is:
```c
typedef struct {
int state;
int proto;
int error;
char addr[1024];
char file[1024];
char user[256];
char passwd[256];
char local[1024];
int topts[4];
gtime_t tnext;
thread_t thread;
} ftp_t;
```
The helper that parses the documented FTP path is:
```c
static void decodeftppath(const char *path, char *addr, char *file, char *user,
char *passwd, int *topts)
{
char buff[MAXSTRPATH], *p, *q;
...
strcpy(buff, path);
...
if ((p = strrchr(buff, '@'))) {
*p++ = '\0';
if ((q = strchr(buff, ':'))) {
*q = '\0';
if (passwd) strcpy(passwd, q + 1);
}
*q = '\0';
if (user) strcpy(user, buff);
}
...
}
```
And `openftp()` passes the embedded `ftp_t` fields directly:
```c
decodeftppath(path, ftp->addr, ftp->file, ftp->user, ftp->passwd, ftp->topts);
```
Why I believe this is a real current-head bug:
1. `stropen()` documents FTP paths as:
```text
STR_FTP [user[:passwd]]@address/file_path[::T=...]
```
2. A path such as:
```text
AAAA...(320 bytes):p@host/file
```
has total length only `332`, which stays below `MAXSTRPATH == 1024`.
3. There is no validation that the parsed username component fits into `ftp->user[256]` before:
```c
if (user) strcpy(user, buff);
```
4. In `ftp_t`, `user[256]` is immediately followed by the live field `passwd[256]`.
So an oversized username causes a direct intra-object overwrite from `user` into `passwd`.
I also built a source-faithful reduced proof preserving the exact `ftp_t` field order and the exact `decodeftppath()` copy logic. The output is:
```text
path_len=332
distance_user_to_passwd=256
user_component_len=320
overflow_bytes_into_passwd=65
passwd_prefix_hex=4141414141414141
local_unchanged=1
```
That result shows:
- the total path remains safely below `1024`
- the overflow does not depend on the already-known `stream->path` bug
- `user[256]` is directly followed by `passwd[256]`
- a `320`-byte username overwrites `65` bytes of the adjacent `passwd` field
I am making a narrow claim:
- this is current-head
- it is reachable from the documented FTP path grammar
- it is a real write-side intra-object overflow
- the concrete overwrite is `ftp->user[256] -> ftp->passwd[256]`
I think the right fix is to validate each parsed component against the actual destination field size and replace these raw `strcpy()` calls with bounded copies.
Best regards
Pengpeng Hou
ISCAS