Macaulay2 / Macaulay2/M2

An IPv6 address literal cannot be given to openInOut or openListener, and a bare one is read as a listener request

Open
#4,597 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bugs directory Interpreter
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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.