An IPv6 address literal cannot be given to openInOut or openListener, and a bare one is read as a listener request
Nobody has claimed this yet.
- Dominant language
- Macaulay2
- Stars
- 435
- Forks
- 297
- Avg merge
- 4d 20h
- Merged PRs (30d)
- 11
Description
This issue was triaged from [`bugs/dan/1-openListener-IPv6`](https://github.com/Macaulay2/M2/blob/388c1ff0ce30d83751dea7bc7eac77fdc1305dd7/bugs/dan/1-openListener-IPv6), one of the 857 files removed from the pre-GitHub `bugs/` tree by [`d2c8d27826`](https://github.com/Macaulay2/M2/commit/d2c8d27826) and catalogued in [#36](https://github.com/Macaulay2/M2/issues/36). **The commentary below was written by Claude (Claude Opus 5, via Claude Code)**, not by @d-torrance, whose account posted it -- please weigh it accordingly.
### The original file, verbatim
```text
add IPv6 IP number parsing to our use of getaddrinfo, somehow.
```
### Where it stands today
IPv6 works. What has no spelling is an IPv6 **address literal**, which is what the one-line
request above is about.
Measured against a server bound to `[::1]:24602`, on 1.26.06-40-gd8e86d689d:
| | by IPv6 name | by IPv6 literal |
| --- | --- | --- |
| `openInOut "$host:port"` | opens the socket | **fails** |
| `SCSCP::newConnection(host, port)` | connects, reaches the handshake | **fails** |
| `getWWW "http://…/"` | `HTTP/1.0 200 OK` | **fails** |
The resolver is already family-agnostic: `openlistener` sets `hints.ai_family = PF_UNSPEC`
(`scclib.c:733`) and `opensocket` passes `NULL` hints, so `getaddrinfo` returns AAAA records and
connects over them. Nothing there needs changing.
### The break is one line above it, and it splits on the first colon
`stdio.d:227-231`:
```
foreach c at j in filename do if c == ':' then (
host0 = substr(filename,1,j-1);
if j+1 < length(filename) then serv = substr(filename,j+1);
break;
);
```
An IPv6 literal is mostly colons, so:
- `"$::1:24601"` — the first colon is at index 1, so `host0` is empty and `serv` is `":1:24601"`.
- `"$[::1]:24601"` — `host0` is `"["` and `serv` is `":1]:24601"`.
Neither reaches `getaddrinfo` intact.
### A bare literal is not rejected, it is reinterpreted
The empty `host0` in the first case is the worse half. `stdio.d:233` reads an empty host as a
request to *listen*:
```
if length(host0) == 0 || listener then ( so = openlistener(host0,serv); ...
```
so `openInOut "$::1:24601"` does not attempt a connection at all — it attempts a bind, with
`":1:24601"` as the service, and reports `can't open listener`. The diagnostic describes an
operation the caller did not ask for.
### Suggested fix
Accept the bracketed authority form from RFC 3986 — `[::1]:2500` — by splitting on the last colon
outside brackets rather than the first colon anywhere. That is the same convention URLs, `ssh -o`,
and `getaddrinfo`'s own callers use, and it leaves the existing `host:port` and bare-`host` forms
untouched since neither contains brackets.
### Two related places, for whoever picks this up
- **`SCSCP/client.m2` already splits correctly and then loses it.** `newConnection String` at
`:77-82` matches `^(.*)\:(.*)$`, and because `.*` is greedy that splits on the *last* colon —
right for IPv6. But `newConnection(String,String)` then rebuilds the string and calls
`openInOut ("$"|hostport)` at `:23`, so `stdio.d` re-splits it on the first colon and undoes the
work.
- **`splitWWW` errors** on `http://[::1]:24602/`, so `getWWW` cannot fetch a bracketed URL even if
the socket layer is fixed. Arguably a separate issue about URL syntax rather than about IPv6.
### Why it is worth the ten lines, and why it is low priority
Low priority: nothing in the tree passes an IP literal, and a hostname is a one-word workaround
that works at every layer.
Worth doing anyway: the literal form is the idiom M2's own documentation teaches. Every socket
example in the tree is an IPv4 literal — `newConnection("127.0.0.1", 26135)` and
`startServer "127.0.0.1"` in the `SCSCP` documentation, the `SCSCP/docinput/*.out` transcripts,
and the bind-to-loopback advice in [#4527](https://github.com/Macaulay2/M2/issues/4527) — and none
of them has an IPv6 spelling.
`open` · disposition `issue` · source of truth: [`bug-triage/catalog.tsv`](https://github.com/d-torrance/M2/blob/bug-triage/bug-triage/catalog.tsv)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the colon-splitting logic in stdio.d:227-233, then inspect scclib.c:733 and the SCSCP/client.m2 connection paths described in the issue. Verify that bracketed IPv6 host-and-port input reaches getaddrinfo intact, that existing host:port and bare-host forms remain unchanged, and that a bare IPv6 literal is not treated as a listener request.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100