Go 1.13.2 corrects a bounds-check proof and DSA verification
A compiler ordering inference could remove a required bounds check. A separate DSA fix rejects a missing modular inverse instead of using it in a multiplication.
Knowing that an index is less than or equal to zero does not establish that it is greater than or equal to zero. A compiler optimization in Go treated a particular ordering relationship as enough evidence for the opposite relationship. Under the conditions documented in the fix, that mistake allowed a required slice bounds check to disappear.
The Go 1.13.2 release entry dates the security release to October 17. The comparison with Go 1.13.1 explains the compiler correction and a separate fix in crypto/dsa. Their common concern is an assumption that needed stronger validation before the next operation.
I depend on Go's ordinary safety checks to make programs readable without reconstructing every machine-level consequence of an access. A bounds-check optimization therefore has to prove the check unnecessary. This release corrects a case where the compiler accepted insufficient evidence for that proof.
Non-strict ordering does not imply equality
The compiler change concerns a partially ordered set used by its reasoning about comparisons. The commit describes a method called OrderedOrEqual that tests whether a relationship such as A <= B is known. It previously accepted a reverse path containing no strict edges as one condition for answering yes.
That condition is insufficient. A known relationship B <= A leaves open both equality and a strict inequality in that direction. The absence of an edge explicitly marked strict does not prove the absence of a strict ordering. Reversing the relationship would therefore assert a fact the compiler has not established.
The commit's example has a loop index ranging over negative one and zero, accessing a slice of length one. An incorrect inference reports that the index is non-negative because a non-strict path relates the index to zero in the opposite direction. That lets the optimizer reason incorrectly about the failed branch of the bounds check.
The patch removes the invalid passing condition. It keeps sufficient conditions such as both values being the same node or a directed path in the direction of the relationship being tested. This is a correction to the proof rules used by the compiler, with a consequence for the generated program's safety behavior.
Another commit in the release renames a method from dominates to reaches. Its explanation distinguishes reachability in a directed acyclic graph from dominance. Reachability is the property the partially ordered set actually needs at those sites. The renaming clarifies the reasoning, while the OrderedOrEqual correction removes the behaviorally incorrect inference.
The failed branch is part of the proof
The compiler commit explains the bounds-check reasoning through facts about both successful and failed accesses. A failed slice check can mean either that the index is negative or that it is at least the slice length. To extract a simpler conclusion, the compiler needs other established facts about the index.
If the optimizer incorrectly believes the index is non-negative, it can conclude that failure requires an index at least as large as the slice. That conclusion conflicts with the loop's known upper bound and the known slice length. The optimizer then treats the failure path as impossible, even though the negative index should make it reachable.
This is why the error is more consequential than an inaccurate diagnostic. The compiler uses its conclusion to change generated control flow. A source-level bounds check can vanish because a proof about its failure path was wrong.
The source comparison documents a specific compiler defect. It does not justify claiming that every slice access in a program loses its check. Exposure depends on the code and the optimizer's reasoning about it. Rebuilding with the corrected compiler removes this defective inference from newly generated programs.
DSA verification must handle an inverse that does not exist
The DSA change addresses malformed public-key parameters. Its commit identifies CVE-2019-17596 and explains that a non-prime Q can cause dsa.Verify to obtain a nil modular inverse. The old implementation then used that nil value in a multiplication, causing a panic.
The patched verification function first checks several input conditions, including ranges for the signature values. It then computes the inverse of s modulo pub.Q. The new branch checks the result before proceeding.
w := new(big.Int).ModInverse(s, pub.Q)
if w == nil {
return false
}
The added check returns the function's normal invalid-signature result when this arithmetic prerequisite fails. A range check on s is insufficient to guarantee that the inverse exists for malformed public-key parameters. The verification function must handle the actual outcome of the inverse operation.
This is a different security boundary from the compiler defect. Here an application reaches a library function with supplied cryptographic values. The function should reject invalid inputs through its boolean result instead of panicking because an intermediate arithmetic assumption failed.
I prefer this kind of local validation because it makes the expected failure behavior clear at the point of use. The inverse is required for the next calculation, so checking it there avoids depending on assumptions about how every caller obtained the public key.
Rebuilding changes two different parts of an executable
Both fixes require attention to built artifacts. The compiler correction changes how future code is generated. The DSA correction changes library code incorporated into programs using that implementation. Updating a toolchain installation leaves previously distributed executables with the code and optimization decisions they already contain.
For the compiler issue, reviewing only an application's direct cryptographic dependencies would miss the relevant scope. For the DSA issue, treating all programs built by the compiler as if they necessarily invoke DSA would overstate the library exposure. These distinctions determine which mechanism matters to a particular executable.
Go 1.13.2 supplies both corrections in one release. Its compiler requires sufficient ordering evidence before removing the bounds check, and its DSA implementation verifies that the needed inverse exists before multiplying by it. The source changes identify the exact assumptions that the earlier implementations failed to establish.