From d4bc01547d1b1a843f1da8d87b20a465af5e35c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20S=C3=A1ez?=
+@@ -810,12 +809,12 @@ from existing types. +
+ +
+-Type = TypeName [ TypeArgs ] | TypeLit | "(" Type ")" .
+-TypeName = identifier | QualifiedIdent .
+-TypeArgs = "[" TypeList [ "," ] "]" .
+-TypeList = Type { "," Type } .
+-TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
+- SliceType | MapType | ChannelType .
++Type = TypeName [ TypeArgs ] | TypeLit | "(" Type ")" .
++TypeName = identifier | QualifiedIdent .
++TypeArgs = "[" TypeList [ "," ] "]" .
++TypeList = Type { "," Type } .
++TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
++ SliceType | MapType | ChannelType .
+
+
+ +@@ -1200,7 +1199,7 @@ type ( +
+ A pointer type denotes the set of all pointers to variables of a given
+ type, called the base type of the pointer.
+-The value of an uninitialized pointer is nil.
++The value of an uninitialized pointer is nil.
+
+@@ -1216,18 +1215,18 @@ BaseType = Type . +Function types
+ ++-A function type denotes the set of all functions with the same parameter +-and result types. The value of an uninitialized variable of function type +-is
+ +nil. ++A function type denotes the set of all functions with the same parameter and result types. ++The value of an uninitialized variable of function ++type isnil. ++-FunctionType = "func" Signature . +-Signature = Parameters [ Result ] . +-Result = Parameters | Type . +-Parameters = "(" [ ParameterList [ "," ] ] ")" . +-ParameterList = ParameterDecl { "," ParameterDecl } . +-ParameterDecl = [ IdentifierList ] [ "..." ] Type . ++FunctionType = "func" Signature . ++Signature = Parameters [ Result ] . ++Result = Parameters | Type . ++Parameters = "(" [ ParameterList [ "," ] ] ")" . ++ParameterList = ParameterDecl { "," ParameterDecl } . ++ParameterDecl = [ IdentifierList ] [ "..." ] Type . ++ ++@@ -1267,7 +1266,8 @@ An interface type defines a type set. + A variable of interface type can store a value of any type that is in the type + set of the interface. Such a type is said to + implement the interface. +-The value of an uninitialized variable of interface type is
+ +nil. ++The value of an uninitialized variable of ++interface type isnil. ++@@ -1630,12 +1630,12 @@ implements the interface. + A map is an unordered group of elements of one type, called the + element type, indexed by a set of unique keys of another type, + called the key type. +-The value of an uninitialized map isnil. ++The value of an uninitialized map isnil. + + ++-MapType = "map" "[" KeyType "]" ElementType . +-KeyType = Type . ++MapType = "map" "[" KeyType "]" ElementType . ++KeyType = Type . ++ ++@@ -1693,7 +1693,7 @@ to communicate by + sending and + receiving + values of a specified element type. +-The value of an uninitialized channel is
+ +nil. ++The value of an uninitialized channel isnil. ++@@ -1772,6 +1772,57 @@ received in the order sent. + +Properties of types and values
+ ++Representation of values
++ ++++Values of predeclared types (see below for the interfaces
++ ++any++anderror), arrays, and structs are self-contained: ++Each such value contains a complete copy of all its data, ++and variables of such types store the entire value. ++For instance, an array variable provides the storage (the variables) ++for all elements of the array. ++The respective zero values are specific to the ++value's types; they are nevernil. ++++Non-nil pointer, function, slice, map, and channel values contain references ++to underlying data which may be shared by multiple values: ++
++ ++
++An interface value may be self-contained or contain references to underlying data
++depending on the interface's dynamic type.
++The predeclared identifier nil is the zero value for types whose values
++can contain references.
++
++When multiple values share underlying data, changing one value may change another. ++For instance, changing an element of a slice will change ++that element in the underlying array for all slices that share the array. ++
++ ++@@ -2176,7 +2227,7 @@ within matching brace brackets. +
+ +
+-Block = "{" StatementList "}" .
++Block = "{" StatementList "}" .
+ StatementList = { Statement ";" } .
+
+
+@@ -2233,8 +2284,8 @@ and like the blank identifier it does not introduce a new binding.
+
+
+ +-Declaration = ConstDecl | TypeDecl | VarDecl . +-TopLevelDecl = Declaration | FunctionDecl | MethodDecl . ++Declaration = ConstDecl | TypeDecl | VarDecl . ++TopLevelDecl = Declaration | FunctionDecl | MethodDecl . ++ +
+@@ -2679,9 +2730,9 @@ in square brackets rather than parentheses +
+ +
+-TypeParameters = "[" TypeParamList [ "," ] "]" .
+-TypeParamList = TypeParamDecl { "," TypeParamDecl } .
+-TypeParamDecl = IdentifierList TypeConstraint .
++TypeParameters = "[" TypeParamList [ "," ] "]" .
++TypeParamList = TypeParamDecl { "," TypeParamDecl } .
++TypeParamDecl = IdentifierList TypeConstraint .
+
+
+ +@@ -2819,7 +2870,7 @@ values or variables, or components of other, non-interface types. + +
+ A type argument T satisfies a type constraint C
+-if T is an element of the type set defined by C; i.e.,
++if T is an element of the type set defined by C; in other words,
+ if T implements C.
+ As an exception, a strictly comparable
+ type constraint may also be satisfied by a comparable
+@@ -2869,8 +2920,8 @@ binds corresponding identifiers to them, and gives each a type and an initial va
+
+-VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
+-VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
++VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
++VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
+
+
+ +@@ -2899,7 +2950,7 @@ initialization value in the assignment. + If that value is an untyped constant, it is first implicitly + converted to its default type; + if it is an untyped boolean value, it is first implicitly converted to typebool. +-The predeclared valuenilcannot be used to initialize a variable ++The predeclared identifiernilcannot be used to initialize a variable + with no explicit type. + + +@@ -3210,15 +3261,15 @@ Each element may optionally be preceded by a corresponding key. + + ++-CompositeLit = LiteralType LiteralValue . +-LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | +- SliceType | MapType | TypeName [ TypeArgs ] . +-LiteralValue = "{" [ ElementList [ "," ] ] "}" . +-ElementList = KeyedElement { "," KeyedElement } . +-KeyedElement = [ Key ":" ] Element . +-Key = FieldName | Expression | LiteralValue . +-FieldName = identifier . +-Element = Expression | LiteralValue . ++CompositeLit = LiteralType LiteralValue . ++LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | ++ SliceType | MapType | TypeName [ TypeArgs ] . ++LiteralValue = "{" [ ElementList [ "," ] ] "}" . ++ElementList = KeyedElement { "," KeyedElement } . ++KeyedElement = [ Key ":" ] Element . ++Key = FieldName | Expression | LiteralValue . ++FieldName = identifier . ++Element = Expression | LiteralValue . ++ ++@@ -3450,22 +3501,21 @@ Primary expressions are the operands for unary and binary expressions. +
+ ++-PrimaryExpr = +- Operand | +- Conversion | +- MethodExpr | +- PrimaryExpr Selector | +- PrimaryExpr Index | +- PrimaryExpr Slice | +- PrimaryExpr TypeAssertion | +- PrimaryExpr Arguments . ++PrimaryExpr = Operand | ++ Conversion | ++ MethodExpr | ++ PrimaryExpr Selector | ++ PrimaryExpr Index | ++ PrimaryExpr Slice | ++ PrimaryExpr TypeAssertion | ++ PrimaryExpr Arguments . + +-Selector = "." identifier . +-Index = "[" Expression [ "," ] "]" . +-Slice = "[" [ Expression ] ":" [ Expression ] "]" | +- "[" [ Expression ] ":" Expression ":" Expression "]" . +-TypeAssertion = "." "(" Type ")" . +-Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" . ++Selector = "." identifier . ++Index = "[" Expression [ "," ] "]" . ++Slice = "[" [ Expression ] ":" [ Expression ] "]" | ++ "[" [ Expression ] ":" Expression ":" Expression "]" . ++TypeAssertion = "." "(" Type ")" . ++Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" . ++ + +@@ -3638,8 +3688,8 @@ argument that is the receiver of the method. + + ++-MethodExpr = ReceiverType "." MethodName . +-ReceiverType = Type . ++MethodExpr = ReceiverType "." MethodName . ++ReceiverType = Type . ++ ++@@ -4230,8 +4280,7 @@ calls
fwith argumentsa1, a2, … an. + Except for one special case, arguments must be single-valued expressions + assignable to the parameter types of +Fand are evaluated before the function is called. +-The type of the expression is the result type +-ofF. ++The type of the expression is the result type ofF. + A method invocation is similar but the method itself + is specified as a selector upon a value of the receiver type for + the method. +@@ -4252,9 +4301,14 @@ or used as a function value. ++ In a function call, the function value and arguments are evaluated in + the usual order. +-After they are evaluated, the parameters of the call are passed by value to the function ++After they are evaluated, new storage is allocated for the function's ++variables, which includes its parameters ++and results. ++Then, the arguments of the call are passed to the function, ++which means that they are assigned ++to their corresponding function parameters, + and the called function begins execution. +-The return parameters of the function are passed by value ++The return parameters of the function are passed + back to the caller when the function returns. +
+ +@@ -4268,9 +4322,9 @@ As a special case, if the return values of a function or method +gare equal in number and individually + assignable to the parameters of another function or method +f, then the callf(g(parameters_of_g))+-will invokefafter binding the return values of +-gto the parameters offin order. The call +-offmust contain no parameters other than the call ofg, ++will invokefafter passing the return values of ++gto the parameters offin order. ++The call offmust contain no parameters other than the call ofg, + andgmust have at least one return value. + Iffhas a final...parameter, it is + assigned the return values ofgthat remain after +@@ -4316,7 +4370,7 @@ Iffis variadic with a final + parameterpof type...T, then withinf+ the type ofpis equivalent to type[]T. + Iffis invoked with no actual arguments forp, +-the value passed topisnil. ++the value passed topisnil. + Otherwise, the value passed is a new slice + of type[]Twith a new underlying array whose successive elements + are the actual arguments, which all must be assignable +@@ -5632,6 +5686,8 @@ myString([]myRune{0x1f30e}) // "\U0001f30e" == "🌎" +
+ []byte("hellø") // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
+@@ -5647,6 +5703,8 @@ bytes("hellø") // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
+
+ []rune(myString("白鵬翔")) // []rune{0x767d, 0x9d6c, 0x7fd4}
+@@ -5848,7 +5906,7 @@ Otherwise, when evaluating the operands of an
+ expression, assignment, or
+ return statement,
+ all function calls, method calls,
+-receive operations,
++receive operations,
+ and binary logical operations
+ are evaluated in lexical left-to-right order.
+
+@@ -5916,11 +5974,10 @@ Statements control execution.
+
+
+
+-Statement =
+- Declaration | LabeledStmt | SimpleStmt |
+- GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
+- FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
+- DeferStmt .
++Statement = Declaration | LabeledStmt | SimpleStmt |
++ GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
++ FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
++ DeferStmt .
+
+ SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
+
+@@ -6132,7 +6189,7 @@ matching number of variables.
+
+ Assignment = ExpressionList assign_op ExpressionList .
+
+-assign_op = [ add_op | mul_op ] "=" .
++assign_op = [ add_op | mul_op ] "=" .
+
+
+
+@@ -6261,6 +6318,26 @@ to the type of the operand to which it is assigned, with the following special c
+
++When a value is assigned to a variable, only the data that is stored in the variable ++is replaced. If the value contains a reference, ++the assignment copies the reference but does not make a copy of the referenced data ++(such as the underlying array of a slice). ++
++ ++
++var s1 = []int{1, 2, 3}
++var s2 = s1 // s2 stores the slice descriptor of s1
++s1 = s1[:1] // s1's length is 1 but it still shares its underlying array with s2
++s2[0] = 42 // setting s2[0] changes s1[0] as well
++fmt.Println(s1, s2) // prints [42] [42 2 3]
++
++var m1 = make(map[string]int)
++var m2 = m1 // m2 stores the map descriptor of m1
++m1["foo"] = 42 // setting m1["foo"] changes m2["foo"] as well
++fmt.Println(m2["foo"]) // prints 42
++
++
+ +@@ -6548,7 +6625,7 @@ The iteration may be controlled by a single condition, a "for" clause, or a "ran +
+ ++-ForStmt = "for" [ Condition | ForClause | RangeClause ] Block . ++ForStmt = "for" [ Condition | ForClause | RangeClause ] Block . + Condition = Expression . ++ +@@ -6580,8 +6657,8 @@ an increment or decrement statement. The init statement may be a + +
+ ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] . +-InitStmt = SimpleStmt . +-PostStmt = SimpleStmt . ++InitStmt = SimpleStmt . ++PostStmt = SimpleStmt . ++ +
+@@ -7909,7 +7986,7 @@ types, variables, and constants. + + ++-SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } . ++SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } . ++ +Package clause
+@@ -7920,8 +7997,8 @@ to which the file belongs. + + ++-PackageClause = "package" PackageName . +-PackageName = identifier . ++PackageClause = "package" PackageName . ++PackageName = identifier . ++ ++@@ -7950,9 +8027,9 @@ that specifies the package to be imported. +
+ ++-ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) . +-ImportSpec = [ "." | PackageName ] ImportPath . +-ImportPath = string_lit . ++ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) . ++ImportSpec = [ "." | PackageName ] ImportPath . ++ImportPath = string_lit . ++ ++diff --git a/doc/initial/1-intro.md b/doc/initial/1-intro.md +index 8c9948ddf6..84ffee855a 100644 +--- a/doc/initial/1-intro.md ++++ b/doc/initial/1-intro.md +@@ -1,9 +1,3 @@ +- +- + +diff --git a/src/builtin/builtin.go b/src/builtin/builtin.go +index af01aea5dd..afa2a10f90 100644 +--- a/src/builtin/builtin.go ++++ b/src/builtin/builtin.go +@@ -162,12 +162,12 @@ func delete(m map[Type]Type1, key Type) + + // The len built-in function returns the length of v, according to its type: + // +-// Array: the number of elements in v. +-// Pointer to array: the number of elements in *v (even if v is nil). +-// Slice, or map: the number of elements in v; if v is nil, len(v) is zero. +-// String: the number of bytes in v. +-// Channel: the number of elements queued (unread) in the channel buffer; +-// if v is nil, len(v) is zero. ++// - Array: the number of elements in v. ++// - Pointer to array: the number of elements in *v (even if v is nil). ++// - Slice, or map: the number of elements in v; if v is nil, len(v) is zero. ++// - String: the number of bytes in v. ++// - Channel: the number of elements queued (unread) in the channel buffer; ++// if v is nil, len(v) is zero. + // + // For some arguments, such as a string literal or a simple array expression, the + // result can be a constant. See the Go language specification's "Length and +@@ -176,12 +176,12 @@ func len(v Type) int + + // The cap built-in function returns the capacity of v, according to its type: + // +-// Array: the number of elements in v (same as len(v)). +-// Pointer to array: the number of elements in *v (same as len(v)). +-// Slice: the maximum length the slice can reach when resliced; +-// if v is nil, cap(v) is zero. +-// Channel: the channel buffer capacity, in units of elements; +-// if v is nil, cap(v) is zero. ++// - Array: the number of elements in v (same as len(v)). ++// - Pointer to array: the number of elements in *v (same as len(v)). ++// - Slice: the maximum length the slice can reach when resliced; ++// if v is nil, cap(v) is zero. ++// - Channel: the channel buffer capacity, in units of elements; ++// if v is nil, cap(v) is zero. + // + // For some arguments, such as a simple array expression, the result can be a + // constant. See the Go language specification's "Length and capacity" section for +@@ -194,18 +194,18 @@ func cap(v Type) int + // argument, not a pointer to it. The specification of the result depends on + // the type: + // +-// Slice: The size specifies the length. The capacity of the slice is +-// equal to its length. A second integer argument may be provided to +-// specify a different capacity; it must be no smaller than the +-// length. For example, make([]int, 0, 10) allocates an underlying array +-// of size 10 and returns a slice of length 0 and capacity 10 that is +-// backed by this underlying array. +-// Map: An empty map is allocated with enough space to hold the +-// specified number of elements. The size may be omitted, in which case +-// a small starting size is allocated. +-// Channel: The channel's buffer is initialized with the specified +-// buffer capacity. If zero, or the size is omitted, the channel is +-// unbuffered. ++// - Slice: The size specifies the length. The capacity of the slice is ++// equal to its length. A second integer argument may be provided to ++// specify a different capacity; it must be no smaller than the ++// length. For example, make([]int, 0, 10) allocates an underlying array ++// of size 10 and returns a slice of length 0 and capacity 10 that is ++// backed by this underlying array. ++// - Map: An empty map is allocated with enough space to hold the ++// specified number of elements. The size may be omitted, in which case ++// a small starting size is allocated. ++// - Channel: The channel's buffer is initialized with the specified ++// buffer capacity. If zero, or the size is omitted, the channel is ++// unbuffered. + func make(t Type, size ...IntegerType) Type + + // The max built-in function returns the largest value of a fixed number of +diff --git a/src/bytes/iter.go b/src/bytes/iter.go +index 1cf13a94ec..9890a478a8 100644 +--- a/src/bytes/iter.go ++++ b/src/bytes/iter.go +@@ -68,7 +68,7 @@ func splitSeq(s, sep []byte, sepSave int) iter.Seq[[]byte] { + } + + // SplitSeq returns an iterator over all substrings of s separated by sep. +-// The iterator yields the same strings that would be returned by Split(s, sep), ++// The iterator yields the same strings that would be returned by [Split](s, sep), + // but without constructing the slice. + // It returns a single-use iterator. + func SplitSeq(s, sep []byte) iter.Seq[[]byte] { +@@ -76,7 +76,7 @@ func SplitSeq(s, sep []byte) iter.Seq[[]byte] { + } + + // SplitAfterSeq returns an iterator over substrings of s split after each instance of sep. +-// The iterator yields the same strings that would be returned by SplitAfter(s, sep), ++// The iterator yields the same strings that would be returned by [SplitAfter](s, sep), + // but without constructing the slice. + // It returns a single-use iterator. + func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] { +@@ -84,8 +84,8 @@ func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] { + } + + // FieldsSeq returns an iterator over substrings of s split around runs of +-// whitespace characters, as defined by unicode.IsSpace. +-// The iterator yields the same strings that would be returned by Fields(s), ++// whitespace characters, as defined by [unicode.IsSpace]. ++// The iterator yields the same strings that would be returned by [Fields](s), + // but without constructing the slice. + func FieldsSeq(s []byte) iter.Seq[[]byte] { + return func(yield func([]byte) bool) { +@@ -118,7 +118,7 @@ func FieldsSeq(s []byte) iter.Seq[[]byte] { + + // FieldsFuncSeq returns an iterator over substrings of s split around runs of + // Unicode code points satisfying f(c). +-// The iterator yields the same strings that would be returned by FieldsFunc(s), ++// The iterator yields the same strings that would be returned by [FieldsFunc](s), + // but without constructing the slice. + func FieldsFuncSeq(s []byte, f func(rune) bool) iter.Seq[[]byte] { + return func(yield func([]byte) bool) { +diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go +index f45df3f86a..49abb857ad 100644 +--- a/src/cmd/compile/doc.go ++++ b/src/cmd/compile/doc.go +@@ -15,7 +15,7 @@ the package and about types used by symbols imported by the package from + other packages. It is therefore not necessary when compiling client C of + package P to read the files of P's dependencies, only the compiled output of P. + +-Command Line ++# Command Line + + Usage: + +@@ -150,14 +150,21 @@ Flags to debug the compiler itself: + -w + Debug type checking. + +-Compiler Directives ++# Compiler Directives + + The compiler accepts directives in the form of comments. +-To distinguish them from non-directive comments, directives +-require no space between the comment opening and the name of the directive. However, since +-they are comments, tools unaware of the directive convention or of a particular ++Each directive must be placed its own line, with only leading spaces and tabs ++allowed before the comment, and there must be no space between the comment ++opening and the name of the directive, to distinguish it from a regular comment. ++Tools unaware of the directive convention or of a particular + directive can skip over a directive like any other comment. ++ ++Other than the line directive, which is a historical special case; ++all other compiler directives are of the form ++//go:name, indicating that they are defined by the Go toolchain. + */ ++// # Line Directives ++// + // Line directives come in several forms: + // + // //line :line +@@ -197,12 +204,9 @@ directive can skip over a directive like any other comment. + // Line directives typically appear in machine-generated code, so that compilers and debuggers + // will report positions in the original input to the generator. + /* +-The line directive is a historical special case; all other directives are of the form +-//go:name, indicating that they are defined by the Go toolchain. +-Each directive must be placed its own line, with only leading spaces and tabs +-allowed before the comment. +-Each directive applies to the Go code that immediately follows it, +-which typically must be a declaration. ++# Function Directives ++ ++A function directive applies to the Go function that immediately follows it. + + //go:noescape + +@@ -245,6 +249,8 @@ It specifies that the function must omit its usual stack overflow check. + This is most commonly used by low-level runtime code invoked + at times when it is unsafe for the calling goroutine to be preempted. + ++# Linkname Directive ++ + //go:linkname localname [importpath.name] + + The //go:linkname directive conventionally precedes the var or func +@@ -295,17 +301,34 @@ The declaration of lower.f may also have a linkname directive with a + single argument, f. This is optional, but helps alert the reader that + the function is accessed from outside the package. + ++# WebAssembly Directives ++ + //go:wasmimport importmodule importname + + The //go:wasmimport directive is wasm-only and must be followed by a +-function declaration. ++function declaration with no body. + It specifies that the function is provided by a wasm module identified +-by ``importmodule`` and ``importname``. ++by ``importmodule'' and ``importname''. For example, + + //go:wasmimport a_module f + func g() + +-The types of parameters and return values to the Go function are translated to ++causes g to refer to the WebAssembly function f from module a_module. ++ ++ //go:wasmexport exportname ++ ++The //go:wasmexport directive is wasm-only and must be followed by a ++function definition. ++It specifies that the function is exported to the wasm host as ``exportname''. ++For example, ++ ++ //go:wasmexport h ++ func hWasm() { ... } ++ ++make Go function hWasm available outside this WebAssembly module as h. ++ ++For both go:wasmimport and go:wasmexport, ++the types of parameters and return values to the Go function are translated to + Wasm according to the following table: + + Go types Wasm types +@@ -318,24 +341,12 @@ Wasm according to the following table: + pointer i32 (more restrictions below) + string (i32, i32) (only permitted as a parameters, not a result) + ++Any other parameter types are disallowed by the compiler. ++ + For a pointer type, its element type must be a bool, int8, uint8, int16, uint16, + int32, uint32, int64, uint64, float32, float64, an array whose element type is + a permitted pointer element type, or a struct, which, if non-empty, embeds +-structs.HostLayout, and contains only fields whose types are permitted pointer ++[structs.HostLayout], and contains only fields whose types are permitted pointer + element types. +- +-Any other parameter types are disallowed by the compiler. +- +- //go:wasmexport exportname +- +-The //go:wasmexport directive is wasm-only and must be followed by a +-function definition. +-It specifies that the function is exported to the wasm host as ``exportname``. +- +- //go:wasmexport f +- func g() +- +-The types of parameters and return values to the Go function are permitted and +-translated to Wasm in the same way as //go:wasmimport functions. + */ + package main +diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go +index dc9b508c01..edd1ffb0c9 100644 +--- a/src/cmd/compile/internal/ssagen/ssa.go ++++ b/src/cmd/compile/internal/ssagen/ssa.go +@@ -5452,12 +5452,15 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value { + if n.X.Type().IsChan() && n.Op() == ir.OCAP { + s.Fatalf("cannot inline cap(chan)") // must use runtime.chancap now + } ++ if n.X.Type().IsMap() && n.Op() == ir.OCAP { ++ s.Fatalf("cannot inline cap(map)") // cap(map) does not exist ++ } + // if n == nil { + // return 0 + // } else { +- // // len +- // return *((*int)n) +- // // cap ++ // // len, the actual loadType depends ++ // return int(*((*loadType)n)) ++ // // cap (chan only, not used for now) + // return *(((*int)n)+1) + // } + lenType := n.Type() +@@ -5485,7 +5488,9 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value { + case ir.OLEN: + if buildcfg.Experiment.SwissMap && n.X.Type().IsMap() { + // length is stored in the first word. +- s.vars[n] = s.load(lenType, x) ++ loadType := reflectdata.SwissMapType().Field(0).Type // uint64 ++ load := s.load(loadType, x) ++ s.vars[n] = s.conv(nil, load, loadType, lenType) // integer conversion doesn't need Node + } else { + // length is stored in the first word for map/chan + s.vars[n] = s.load(lenType, x) +diff --git a/src/cmd/compile/internal/syntax/testdata/issue70974.go b/src/cmd/compile/internal/syntax/testdata/issue70974.go +new file mode 100644 +index 0000000000..ebc69eda95 +--- /dev/null ++++ b/src/cmd/compile/internal/syntax/testdata/issue70974.go +@@ -0,0 +1,17 @@ ++// Copyright 2025 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package p ++ ++func _() { ++M: ++L: ++ for range 0 { ++ break L ++ break /* ERROR invalid break label M */ M ++ } ++ for range 0 { ++ break /* ERROR invalid break label L */ L ++ } ++} +diff --git a/src/cmd/compile/internal/types2/README.md b/src/cmd/compile/internal/types2/README.md +index 3d70cdbcf4..73253b4920 100644 +--- a/src/cmd/compile/internal/types2/README.md ++++ b/src/cmd/compile/internal/types2/README.md +@@ -56,7 +56,7 @@ The tests are in: + Tests are .go files annotated with `/* ERROR "msg" */` or `/* ERRORx "msg" */` + comments (or the respective line comment form). + For each such error comment, typechecking the respective file is expected to +-report an error at the position of the syntactic token _immediately preceeding_ ++report an error at the position of the syntactic token _immediately preceding_ + the comment. + For `ERROR`, the `"msg"` string must be a substring of the error message + reported by the typechecker; +diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go +index 74c549076d..49cc0e54ec 100644 +--- a/src/cmd/compile/internal/types2/api.go ++++ b/src/cmd/compile/internal/types2/api.go +@@ -208,11 +208,19 @@ type Info struct { + // + // The Types map does not record the type of every identifier, + // only those that appear where an arbitrary expression is +- // permitted. For instance, the identifier f in a selector +- // expression x.f is found only in the Selections map, the +- // identifier z in a variable declaration 'var z int' is found +- // only in the Defs map, and identifiers denoting packages in +- // qualified identifiers are collected in the Uses map. ++ // permitted. For instance: ++ // - an identifier f in a selector expression x.f is found ++ // only in the Selections map; ++ // - an identifier z in a variable declaration 'var z int' ++ // is found only in the Defs map; ++ // - an identifier p denoting a package in a qualified ++ // identifier p.X is found only in the Uses map. ++ // ++ // Similarly, no type is recorded for the (synthetic) FuncType ++ // node in a FuncDecl.Type field, since there is no corresponding ++ // syntactic function type expression in the source in this case ++ // Instead, the function type is found in the Defs.map entry for ++ // the corresponding function declaration. + Types map[syntax.Expr]TypeAndValue + + // If StoreTypesInSyntax is set, type information identical to +diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go +index d3169630ea..de4f1eaa20 100644 +--- a/src/cmd/compile/internal/types2/signature.go ++++ b/src/cmd/compile/internal/types2/signature.go +@@ -174,7 +174,7 @@ func (check *Checker) collectRecv(rparam *syntax.Field, scopePos syntax.Pos) (*V + } else { + // If there are type parameters, rbase must denote a generic base type. + // Important: rbase must be resolved before declaring any receiver type +- // parameters (wich may have the same name, see below). ++ // parameters (which may have the same name, see below). + var baseType *Named // nil if not valid + var cause string + if t := check.genericType(rbase, &cause); isValid(t) { +diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go +index 5a981f8bc1..0c992118f4 100644 +--- a/src/cmd/dist/test.go ++++ b/src/cmd/dist/test.go +@@ -876,16 +876,18 @@ func (t *tester) registerTests() { + } + + if t.extLink() && !t.compileOnly { +- t.registerTest("external linking, -buildmode=exe", +- &goTest{ +- variant: "exe_external", +- timeout: 60 * time.Second, +- buildmode: "exe", +- ldflags: "-linkmode=external", +- env: []string{"CGO_ENABLED=1"}, +- pkg: "crypto/internal/fips140test", +- runTests: "TestFIPSCheck", +- }) ++ if goos != "android" { // Android does not support non-PIE linking ++ t.registerTest("external linking, -buildmode=exe", ++ &goTest{ ++ variant: "exe_external", ++ timeout: 60 * time.Second, ++ buildmode: "exe", ++ ldflags: "-linkmode=external", ++ env: []string{"CGO_ENABLED=1"}, ++ pkg: "crypto/internal/fips140test", ++ runTests: "TestFIPSCheck", ++ }) ++ } + if t.externalLinkPIE() && !disablePIE { + t.registerTest("external linking, -buildmode=pie", + &goTest{ +@@ -1795,6 +1797,8 @@ func isEnvSet(evar string) bool { + } + + func (t *tester) fipsSupported() bool { ++ // Keep this in sync with [crypto/internal/fips140.Supported]. ++ + // Use GOFIPS140 or GOEXPERIMENT=boringcrypto, but not both. + if strings.Contains(goexperiment, "boringcrypto") { + return false +@@ -1808,6 +1812,7 @@ func (t *tester) fipsSupported() bool { + case goarch == "wasm", + goos == "windows" && goarch == "386", + goos == "windows" && goarch == "arm", ++ goos == "openbsd", + goos == "aix": + return false + } +diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go +index 3a4473902c..20d76de0c7 100644 +--- a/src/cmd/go/alldocs.go ++++ b/src/cmd/go/alldocs.go +@@ -739,11 +739,6 @@ + // + // For more about specifying packages, see 'go help packages'. + // +-// This text describes the behavior of get using modules to manage source +-// code and dependencies. If instead the go command is running in GOPATH +-// mode, the details of get's flags and effects change, as does 'go help get'. +-// See 'go help gopath-get'. +-// + // See also: go build, go install, go clean, go mod. + // + // # Compile and install packages and dependencies +@@ -2186,7 +2181,7 @@ + // fields of all events to reconstruct the text format output, as it would + // have appeared from go build without the -json flag. + // +-// Note that there may also be non-JSON error text on stdnard error, even ++// Note that there may also be non-JSON error text on standard error, even + // with the -json flag. Typically, this indicates an early, serious error. + // Consumers should be robust to this. + // +@@ -2250,7 +2245,7 @@ + // + // The second is the SWIG program, which is a general tool for + // interfacing between languages. For information on SWIG see +-// http://swig.org/. When running go build, any file with a .swig ++// https://swig.org/. When running go build, any file with a .swig + // extension will be passed to SWIG. Any file with a .swigcxx extension + // will be passed to SWIG with the -c++ option. + // +@@ -2338,6 +2333,10 @@ + // GOCACHE + // The directory where the go command will store cached + // information for reuse in future builds. ++// GOCACHEPROG ++// A command (with optional space-separated flags) that implements an ++// external go command build cache. ++// See 'go doc cmd/go/internal/cacheprog'. + // GODEBUG + // Enable various debugging facilities. See https://go.dev/doc/godebug + // for details. +@@ -2448,6 +2447,11 @@ + // GOARM + // For GOARCH=arm, the ARM architecture for which to compile. + // Valid values are 5, 6, 7. ++// When the Go tools are built on an arm system, ++// the default value is set based on what the build system supports. ++// When the Go tools are not built on an arm system ++// (that is, when building a cross-compiler), ++// the default value is 7. + // The value can be followed by an option specifying how to implement floating point instructions. + // Valid options are ,softfloat (default for 5) and ,hardfloat (default for 6 and 7). + // GOARM64 +@@ -2612,7 +2616,7 @@ + // Example: Data + // + // If the server responds with any 4xx code, the go command will write the +-// following to the programs' stdin: ++// following to the program's stdin: + // Response = StatusLine { HeaderLine } BlankLine . + // StatusLine = Protocol Space Status '\n' . + // Protocol = /* HTTP protocol */ . +@@ -2969,11 +2973,7 @@ + // same meta tag and then git clone https://code.org/r/p/exproj into + // GOPATH/src/example.org. + // +-// When using GOPATH, downloaded packages are written to the first directory +-// listed in the GOPATH environment variable. +-// (See 'go help gopath-get' and 'go help gopath'.) +-// +-// When using modules, downloaded packages are stored in the module cache. ++// Downloaded packages are stored in the module cache. + // See https://golang.org/ref/mod#module-cache. + // + // When using modules, an additional variant of the go-import meta tag is +diff --git a/src/cmd/go/internal/cache/cache.go b/src/cmd/go/internal/cache/cache.go +index 98bed2a595..1bef1db08c 100644 +--- a/src/cmd/go/internal/cache/cache.go ++++ b/src/cmd/go/internal/cache/cache.go +@@ -38,8 +38,8 @@ type Cache interface { + // Get returns the cache entry for the provided ActionID. + // On miss, the error type should be of type *entryNotFoundError. + // +- // After a success call to Get, OutputFile(Entry.OutputID) must +- // exist on disk for until Close is called (at the end of the process). ++ // After a successful call to Get, OutputFile(Entry.OutputID) must ++ // exist on disk until Close is called (at the end of the process). + Get(ActionID) (Entry, error) + + // Put adds an item to the cache. +@@ -50,14 +50,14 @@ type Cache interface { + // As a special case, if the ReadSeeker is of type noVerifyReadSeeker, + // the verification from GODEBUG=goverifycache=1 is skipped. + // +- // After a success call to Get, OutputFile(Entry.OutputID) must +- // exist on disk for until Close is called (at the end of the process). ++ // After a successful call to Put, OutputFile(OutputID) must ++ // exist on disk until Close is called (at the end of the process). + Put(ActionID, io.ReadSeeker) (_ OutputID, size int64, _ error) + + // Close is called at the end of the go process. Implementations can do + // cache cleanup work at this phase, or wait for and report any errors from +- // background cleanup work started earlier. Any cache trimming should in one +- // process should not violate cause the invariants of this interface to be ++ // background cleanup work started earlier. Any cache trimming in one ++ // process should not cause the invariants of this interface to be + // violated in another process. Namely, a cache trim from one process should + // not delete an ObjectID from disk that was recently Get or Put from + // another process. As a rule of thumb, don't trim things used in the last +@@ -296,19 +296,19 @@ func GetBytes(c Cache, id ActionID) ([]byte, Entry, error) { + // GetMmap looks up the action ID in the cache and returns + // the corresponding output bytes. + // GetMmap should only be used for data that can be expected to fit in memory. +-func GetMmap(c Cache, id ActionID) ([]byte, Entry, error) { ++func GetMmap(c Cache, id ActionID) ([]byte, Entry, bool, error) { + entry, err := c.Get(id) + if err != nil { +- return nil, entry, err ++ return nil, entry, false, err + } +- md, err := mmap.Mmap(c.OutputFile(entry.OutputID)) ++ md, opened, err := mmap.Mmap(c.OutputFile(entry.OutputID)) + if err != nil { +- return nil, Entry{}, err ++ return nil, Entry{}, opened, err + } + if int64(len(md.Data)) != entry.Size { +- return nil, Entry{}, &entryNotFoundError{Err: errors.New("file incomplete")} ++ return nil, Entry{}, true, &entryNotFoundError{Err: errors.New("file incomplete")} + } +- return md.Data, entry, nil ++ return md.Data, entry, true, nil + } + + // OutputFile returns the name of the cache file storing output with the given OutputID. +diff --git a/src/cmd/go/internal/cache/default.go b/src/cmd/go/internal/cache/default.go +index 074f911593..f8e5696cbd 100644 +--- a/src/cmd/go/internal/cache/default.go ++++ b/src/cmd/go/internal/cache/default.go +@@ -54,8 +54,8 @@ func initDefaultCache() Cache { + base.Fatalf("failed to initialize build cache at %s: %s\n", dir, err) + } + +- if v := cfg.Getenv("GOCACHEPROG"); v != "" { +- return startCacheProg(v, diskCache) ++ if cfg.GOCACHEPROG != "" { ++ return startCacheProg(cfg.GOCACHEPROG, diskCache) + } + + return diskCache +diff --git a/src/cmd/go/internal/cache/prog.go b/src/cmd/go/internal/cache/prog.go +index e09620bac8..bfddf5e4de 100644 +--- a/src/cmd/go/internal/cache/prog.go ++++ b/src/cmd/go/internal/cache/prog.go +@@ -7,6 +7,7 @@ package cache + import ( + "bufio" + "cmd/go/internal/base" ++ "cmd/go/internal/cacheprog" + "cmd/internal/quoted" + "context" + "crypto/sha256" +@@ -38,7 +39,7 @@ type ProgCache struct { + + // can are the commands that the child process declared that it supports. + // This is effectively the versioning mechanism. +- can map[ProgCmd]bool ++ can map[cacheprog.Cmd]bool + + // fuzzDirCache is another Cache implementation to use for the FuzzDir + // method. In practice this is the default GOCACHE disk-based +@@ -55,7 +56,7 @@ type ProgCache struct { + + mu sync.Mutex // guards following fields + nextID int64 +- inFlight map[int64]chan<- *ProgResponse ++ inFlight map[int64]chan<- *cacheprog.Response + outputFile map[OutputID]string // object => abs path on disk + + // writeMu serializes writing to the child process. +@@ -63,95 +64,6 @@ type ProgCache struct { + writeMu sync.Mutex + } + +-// ProgCmd is a command that can be issued to a child process. +-// +-// If the interface needs to grow, we can add new commands or new versioned +-// commands like "get2". +-type ProgCmd string +- +-const ( +- cmdGet = ProgCmd("get") +- cmdPut = ProgCmd("put") +- cmdClose = ProgCmd("close") +-) +- +-// ProgRequest is the JSON-encoded message that's sent from cmd/go to +-// the GOCACHEPROG child process over stdin. Each JSON object is on its +-// own line. A ProgRequest of Type "put" with BodySize > 0 will be followed +-// by a line containing a base64-encoded JSON string literal of the body. +-type ProgRequest struct { +- // ID is a unique number per process across all requests. +- // It must be echoed in the ProgResponse from the child. +- ID int64 +- +- // Command is the type of request. +- // The cmd/go tool will only send commands that were declared +- // as supported by the child. +- Command ProgCmd +- +- // ActionID is non-nil for get and puts. +- ActionID []byte `json:",omitempty"` // or nil if not used +- +- // OutputID is set for Type "put". +- // +- // Prior to Go 1.24, when GOCACHEPROG was still an experiment, this was +- // accidentally named ObjectID. It was renamed to OutputID in Go 1.24. +- OutputID []byte `json:",omitempty"` // or nil if not used +- +- // Body is the body for "put" requests. It's sent after the JSON object +- // as a base64-encoded JSON string when BodySize is non-zero. +- // It's sent as a separate JSON value instead of being a struct field +- // send in this JSON object so large values can be streamed in both directions. +- // The base64 string body of a ProgRequest will always be written +- // immediately after the JSON object and a newline. +- Body io.Reader `json:"-"` +- +- // BodySize is the number of bytes of Body. If zero, the body isn't written. +- BodySize int64 `json:",omitempty"` +- +- // ObjectID is the accidental spelling of OutputID that was used prior to Go +- // 1.24. +- // +- // Deprecated: use OutputID. This field is only populated temporarily for +- // backwards compatibility with Go 1.23 and earlier when +- // GOEXPERIMENT=gocacheprog is set. It will be removed in Go 1.25. +- ObjectID []byte `json:",omitempty"` +-} +- +-// ProgResponse is the JSON response from the child process to cmd/go. +-// +-// With the exception of the first protocol message that the child writes to its +-// stdout with ID==0 and KnownCommands populated, these are only sent in +-// response to a ProgRequest from cmd/go. +-// +-// ProgResponses can be sent in any order. The ID must match the request they're +-// replying to. +-type ProgResponse struct { +- ID int64 // that corresponds to ProgRequest; they can be answered out of order +- Err string `json:",omitempty"` // if non-empty, the error +- +- // KnownCommands is included in the first message that cache helper program +- // writes to stdout on startup (with ID==0). It includes the +- // ProgRequest.Command types that are supported by the program. +- // +- // This lets us extend the protocol gracefully over time (adding "get2", +- // etc), or fail gracefully when needed. It also lets us verify the program +- // wants to be a cache helper. +- KnownCommands []ProgCmd `json:",omitempty"` +- +- // For Get requests. +- +- Miss bool `json:",omitempty"` // cache miss +- OutputID []byte `json:",omitempty"` +- Size int64 `json:",omitempty"` // in bytes +- Time *time.Time `json:",omitempty"` // an Entry.Time; when the object was added to the docs +- +- // DiskPath is the absolute path on disk of the ObjectID corresponding +- // a "get" request's ActionID (on cache hit) or a "put" request's +- // provided ObjectID. +- DiskPath string `json:",omitempty"` +-} +- + // startCacheProg starts the prog binary (with optional space-separated flags) + // and returns a Cache implementation that talks to it. + // +@@ -183,6 +95,8 @@ func startCacheProg(progAndArgs string, fuzzDirCache Cache) Cache { + base.Fatalf("StdinPipe to GOCACHEPROG: %v", err) + } + cmd.Stderr = os.Stderr ++ // On close, we cancel the context. Rather than killing the helper, ++ // close its stdin. + cmd.Cancel = in.Close + + if err := cmd.Start(); err != nil { +@@ -197,14 +111,14 @@ func startCacheProg(progAndArgs string, fuzzDirCache Cache) Cache { + stdout: out, + stdin: in, + bw: bufio.NewWriter(in), +- inFlight: make(map[int64]chan<- *ProgResponse), ++ inFlight: make(map[int64]chan<- *cacheprog.Response), + outputFile: make(map[OutputID]string), + readLoopDone: make(chan struct{}), + } + + // Register our interest in the initial protocol message from the child to + // us, saying what it can do. +- capResc := make(chan *ProgResponse, 1) ++ capResc := make(chan *cacheprog.Response, 1) + pc.inFlight[0] = capResc + + pc.jenc = json.NewEncoder(pc.bw) +@@ -219,7 +133,7 @@ func startCacheProg(progAndArgs string, fuzzDirCache Cache) Cache { + case <-timer.C: + log.Printf("# still waiting for GOCACHEPROG %v ...", prog) + case capRes := <-capResc: +- can := map[ProgCmd]bool{} ++ can := map[cacheprog.Cmd]bool{} + for _, cmd := range capRes.KnownCommands { + can[cmd] = true + } +@@ -236,9 +150,15 @@ func (c *ProgCache) readLoop(readLoopDone chan<- struct{}) { + defer close(readLoopDone) + jd := json.NewDecoder(c.stdout) + for { +- res := new(ProgResponse) ++ res := new(cacheprog.Response) + if err := jd.Decode(res); err != nil { + if c.closing.Load() { ++ c.mu.Lock() ++ for _, ch := range c.inFlight { ++ close(ch) ++ } ++ c.inFlight = nil ++ c.mu.Unlock() + return // quietly + } + if err == io.EOF { +@@ -261,13 +181,18 @@ func (c *ProgCache) readLoop(readLoopDone chan<- struct{}) { + } + } + +-func (c *ProgCache) send(ctx context.Context, req *ProgRequest) (*ProgResponse, error) { +- resc := make(chan *ProgResponse, 1) ++var errCacheprogClosed = errors.New("GOCACHEPROG program closed unexpectedly") ++ ++func (c *ProgCache) send(ctx context.Context, req *cacheprog.Request) (*cacheprog.Response, error) { ++ resc := make(chan *cacheprog.Response, 1) + if err := c.writeToChild(req, resc); err != nil { + return nil, err + } + select { + case res := <-resc: ++ if res == nil { ++ return nil, errCacheprogClosed ++ } + if res.Err != "" { + return nil, errors.New(res.Err) + } +@@ -277,8 +202,11 @@ func (c *ProgCache) send(ctx context.Context, req *ProgRequest) (*ProgResponse, + } + } + +-func (c *ProgCache) writeToChild(req *ProgRequest, resc chan<- *ProgResponse) (err error) { ++func (c *ProgCache) writeToChild(req *cacheprog.Request, resc chan<- *cacheprog.Response) (err error) { + c.mu.Lock() ++ if c.inFlight == nil { ++ return errCacheprogClosed ++ } + c.nextID++ + req.ID = c.nextID + c.inFlight[req.ID] = resc +@@ -287,7 +215,9 @@ func (c *ProgCache) writeToChild(req *ProgRequest, resc chan<- *ProgResponse) (e + defer func() { + if err != nil { + c.mu.Lock() +- delete(c.inFlight, req.ID) ++ if c.inFlight != nil { ++ delete(c.inFlight, req.ID) ++ } + c.mu.Unlock() + } + }() +@@ -328,7 +258,7 @@ func (c *ProgCache) writeToChild(req *ProgRequest, resc chan<- *ProgResponse) (e + } + + func (c *ProgCache) Get(a ActionID) (Entry, error) { +- if !c.can[cmdGet] { ++ if !c.can[cacheprog.CmdGet] { + // They can't do a "get". Maybe they're a write-only cache. + // + // TODO(bradfitz,bcmills): figure out the proper error type here. Maybe +@@ -338,8 +268,8 @@ func (c *ProgCache) Get(a ActionID) (Entry, error) { + // error types on the Cache interface. + return Entry{}, &entryNotFoundError{} + } +- res, err := c.send(c.ctx, &ProgRequest{ +- Command: cmdGet, ++ res, err := c.send(c.ctx, &cacheprog.Request{ ++ Command: cacheprog.CmdGet, + ActionID: a[:], + }) + if err != nil { +@@ -395,7 +325,7 @@ func (c *ProgCache) Put(a ActionID, file io.ReadSeeker) (_ OutputID, size int64, + return OutputID{}, 0, err + } + +- if !c.can[cmdPut] { ++ if !c.can[cacheprog.CmdPut] { + // Child is a read-only cache. Do nothing. + return out, size, nil + } +@@ -407,8 +337,8 @@ func (c *ProgCache) Put(a ActionID, file io.ReadSeeker) (_ OutputID, size int64, + deprecatedValue = out[:] + } + +- res, err := c.send(c.ctx, &ProgRequest{ +- Command: cmdPut, ++ res, err := c.send(c.ctx, &cacheprog.Request{ ++ Command: cacheprog.CmdPut, + ActionID: a[:], + OutputID: out[:], + ObjectID: deprecatedValue, // TODO(bradfitz): remove in Go 1.25 +@@ -432,10 +362,16 @@ func (c *ProgCache) Close() error { + // First write a "close" message to the child so it can exit nicely + // and clean up if it wants. Only after that exchange do we cancel + // the context that kills the process. +- if c.can[cmdClose] { +- _, err = c.send(c.ctx, &ProgRequest{Command: cmdClose}) ++ if c.can[cacheprog.CmdClose] { ++ _, err = c.send(c.ctx, &cacheprog.Request{Command: cacheprog.CmdClose}) ++ if errors.Is(err, errCacheprogClosed) { ++ // Allow the child to quit without responding to close. ++ err = nil ++ } + } ++ // Cancel the context, which will close the helper's stdin. + c.ctxCancel() ++ // Wait until the helper closes its stdout. + <-c.readLoopDone + return err + } +diff --git a/src/cmd/go/internal/cacheprog/cacheprog.go b/src/cmd/go/internal/cacheprog/cacheprog.go +new file mode 100644 +index 0000000000..a2796592df +--- /dev/null ++++ b/src/cmd/go/internal/cacheprog/cacheprog.go +@@ -0,0 +1,137 @@ ++// Copyright 2024 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package cacheprog defines the protocol for a GOCACHEPROG program. ++// ++// By default, the go command manages a build cache stored in the file system ++// itself. GOCACHEPROG can be set to the name of a command (with optional ++// space-separated flags) that implements the go command build cache externally. ++// This permits defining a different cache policy. ++// ++// The go command will start the GOCACHEPROG as a subprocess and communicate ++// with it via JSON messages over stdin/stdout. The subprocess's stderr will be ++// connected to the go command's stderr. ++// ++// The subprocess should immediately send a [Response] with its capabilities. ++// After that, the go command will send a stream of [Request] messages and the ++// subprocess should reply to each [Request] with a [Response] message. ++package cacheprog ++ ++import ( ++ "io" ++ "time" ++) ++ ++// Cmd is a command that can be issued to a child process. ++// ++// If the interface needs to grow, the go command can add new commands or new ++// versioned commands like "get2" in the future. The initial [Response] from ++// the child process indicates which commands it supports. ++type Cmd string ++ ++const ( ++ // CmdPut tells the cache program to store an object in the cache. ++ // ++ // [Request.ActionID] is the cache key of this object. The cache should ++ // store [Request.OutputID] and [Request.Body] under this key for a ++ // later "get" request. It must also store the Body in a file in the local ++ // file system and return the path to that file in [Response.DiskPath], ++ // which must exist at least until a "close" request. ++ CmdPut = Cmd("put") ++ ++ // CmdGet tells the cache program to retrieve an object from the cache. ++ // ++ // [Request.ActionID] specifies the key of the object to get. If the ++ // cache does not contain this object, it should set [Response.Miss] to ++ // true. Otherwise, it should populate the fields of [Response], ++ // including setting [Response.OutputID] to the OutputID of the original ++ // "put" request and [Response.DiskPath] to the path of a local file ++ // containing the Body of the original "put" request. That file must ++ // continue to exist at least until a "close" request. ++ CmdGet = Cmd("get") ++ ++ // CmdClose requests that the cache program exit gracefully. ++ // ++ // The cache program should reply to this request and then exit ++ // (thus closing its stdout). ++ CmdClose = Cmd("close") ++) ++ ++// Request is the JSON-encoded message that's sent from the go command to ++// the GOCACHEPROG child process over stdin. Each JSON object is on its own ++// line. A ProgRequest of Type "put" with BodySize > 0 will be followed by a ++// line containing a base64-encoded JSON string literal of the body. ++type Request struct { ++ // ID is a unique number per process across all requests. ++ // It must be echoed in the Response from the child. ++ ID int64 ++ ++ // Command is the type of request. ++ // The go command will only send commands that were declared ++ // as supported by the child. ++ Command Cmd ++ ++ // ActionID is the cache key for "put" and "get" requests. ++ ActionID []byte `json:",omitempty"` // or nil if not used ++ ++ // OutputID is stored with the body for "put" requests. ++ // ++ // Prior to Go 1.24, when GOCACHEPROG was still an experiment, this was ++ // accidentally named ObjectID. It was renamed to OutputID in Go 1.24. ++ OutputID []byte `json:",omitempty"` // or nil if not used ++ ++ // Body is the body for "put" requests. It's sent after the JSON object ++ // as a base64-encoded JSON string when BodySize is non-zero. ++ // It's sent as a separate JSON value instead of being a struct field ++ // send in this JSON object so large values can be streamed in both directions. ++ // The base64 string body of a Request will always be written ++ // immediately after the JSON object and a newline. ++ Body io.Reader `json:"-"` ++ ++ // BodySize is the number of bytes of Body. If zero, the body isn't written. ++ BodySize int64 `json:",omitempty"` ++ ++ // ObjectID is the accidental spelling of OutputID that was used prior to Go ++ // 1.24. ++ // ++ // Deprecated: use OutputID. This field is only populated temporarily for ++ // backwards compatibility with Go 1.23 and earlier when ++ // GOEXPERIMENT=gocacheprog is set. It will be removed in Go 1.25. ++ ObjectID []byte `json:",omitempty"` ++} ++ ++// Response is the JSON response from the child process to the go command. ++// ++// With the exception of the first protocol message that the child writes to its ++// stdout with ID==0 and KnownCommands populated, these are only sent in ++// response to a Request from the go command. ++// ++// Responses can be sent in any order. The ID must match the request they're ++// replying to. ++type Response struct { ++ ID int64 // that corresponds to Request; they can be answered out of order ++ Err string `json:",omitempty"` // if non-empty, the error ++ ++ // KnownCommands is included in the first message that cache helper program ++ // writes to stdout on startup (with ID==0). It includes the ++ // Request.Command types that are supported by the program. ++ // ++ // This lets the go command extend the protocol gracefully over time (adding ++ // "get2", etc), or fail gracefully when needed. It also lets the go command ++ // verify the program wants to be a cache helper. ++ KnownCommands []Cmd `json:",omitempty"` ++ ++ // For "get" requests. ++ ++ Miss bool `json:",omitempty"` // cache miss ++ OutputID []byte `json:",omitempty"` // the ObjectID stored with the body ++ Size int64 `json:",omitempty"` // body size in bytes ++ Time *time.Time `json:",omitempty"` // when the object was put in the cache (optional; used for cache expiration) ++ ++ // For "get" and "put" requests. ++ ++ // DiskPath is the absolute path on disk of the body corresponding to a ++ // "get" (on cache hit) or "put" request's ActionID. ++ DiskPath string `json:",omitempty"` ++} +diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go +index 6c2af99c2d..3b9f27e91d 100644 +--- a/src/cmd/go/internal/cfg/cfg.go ++++ b/src/cmd/go/internal/cfg/cfg.go +@@ -425,8 +425,9 @@ var ( + GOROOTpkg string + GOROOTsrc string + +- GOBIN = Getenv("GOBIN") +- GOMODCACHE, GOMODCACHEChanged = EnvOrAndChanged("GOMODCACHE", gopathDir("pkg/mod")) ++ GOBIN = Getenv("GOBIN") ++ GOCACHEPROG, GOCACHEPROGChanged = EnvOrAndChanged("GOCACHEPROG", "") ++ GOMODCACHE, GOMODCACHEChanged = EnvOrAndChanged("GOMODCACHE", gopathDir("pkg/mod")) + + // Used in envcmd.MkEnv and build ID computations. + GOARM64, goARM64Changed = EnvOrAndChanged("GOARM64", buildcfg.DefaultGOARM64) +diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go +index 19db68e4f8..7c370d427f 100644 +--- a/src/cmd/go/internal/envcmd/env.go ++++ b/src/cmd/go/internal/envcmd/env.go +@@ -85,6 +85,7 @@ func MkEnv() []cfg.EnvVar { + {Name: "GOAUTH", Value: cfg.GOAUTH, Changed: cfg.GOAUTHChanged}, + {Name: "GOBIN", Value: cfg.GOBIN}, + {Name: "GOCACHE"}, ++ {Name: "GOCACHEPROG", Value: cfg.GOCACHEPROG, Changed: cfg.GOCACHEPROGChanged}, + {Name: "GODEBUG", Value: os.Getenv("GODEBUG")}, + {Name: "GOENV", Value: envFile, Changed: envFileChanged}, + {Name: "GOEXE", Value: cfg.ExeSuffix}, +diff --git a/src/cmd/go/internal/fips140/fips140.go b/src/cmd/go/internal/fips140/fips140.go +index 7c04a94dd1..328e06088e 100644 +--- a/src/cmd/go/internal/fips140/fips140.go ++++ b/src/cmd/go/internal/fips140/fips140.go +@@ -40,14 +40,8 @@ + // + // GOFIPS140=latest go build -work my/binary + // +-// will leave fips.o behind in $WORK/b001. Auditors like to be able to +-// see that file. Accordingly, when [Enabled] returns true, +-// [cmd/go/internal/work.Builder.useCache] arranges never to cache linker +-// output, so that the link step always runs, and fips.o is always left +-// behind in the link step. If this proves too slow, we could always +-// cache fips.o as an extra link output and then restore it when -work is +-// set, but we went a very long time never caching link steps at all, so +-// not caching them in FIPS mode seems perfectly fine. ++// will leave fips.o behind in $WORK/b001 ++// (unless the build result is cached, of course). + // + // When GOFIPS140 is set to something besides off and latest, [Snapshot] + // returns true, indicating that the build should replace the latest copy +@@ -119,6 +113,10 @@ func Init() { + if Snapshot() { + fsys.Bind(Dir(), filepath.Join(cfg.GOROOT, "src/crypto/internal/fips140")) + } ++ ++ if cfg.Experiment.BoringCrypto && Enabled() { ++ base.Fatalf("go: cannot use GOFIPS140 with GOEXPERIMENT=boringcrypto") ++ } + } + + var initDone bool +diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go +index e1240de710..65d0f1a45c 100644 +--- a/src/cmd/go/internal/help/helpdoc.go ++++ b/src/cmd/go/internal/help/helpdoc.go +@@ -17,7 +17,7 @@ information on how to use it see the cgo documentation (go doc cmd/cgo). + + The second is the SWIG program, which is a general tool for + interfacing between languages. For information on SWIG see +-http://swig.org/. When running go build, any file with a .swig ++https://swig.org/. When running go build, any file with a .swig + extension will be passed to SWIG. Any file with a .swigcxx extension + will be passed to SWIG with the -c++ option. + +@@ -270,11 +270,7 @@ the go tool will verify that https://example.org/?go-get=1 contains the + same meta tag and then git clone https://code.org/r/p/exproj into + GOPATH/src/example.org. + +-When using GOPATH, downloaded packages are written to the first directory +-listed in the GOPATH environment variable. +-(See 'go help gopath-get' and 'go help gopath'.) +- +-When using modules, downloaded packages are stored in the module cache. ++Downloaded packages are stored in the module cache. + See https://golang.org/ref/mod#module-cache. + + When using modules, an additional variant of the go-import meta tag is +@@ -510,6 +506,10 @@ General-purpose environment variables: + GOCACHE + The directory where the go command will store cached + information for reuse in future builds. ++ GOCACHEPROG ++ A command (with optional space-separated flags) that implements an ++ external go command build cache. ++ See 'go doc cmd/go/internal/cacheprog'. + GODEBUG + Enable various debugging facilities. See https://go.dev/doc/godebug + for details. +@@ -620,6 +620,11 @@ Architecture-specific environment variables: + GOARM + For GOARCH=arm, the ARM architecture for which to compile. + Valid values are 5, 6, 7. ++ When the Go tools are built on an arm system, ++ the default value is set based on what the build system supports. ++ When the Go tools are not built on an arm system ++ (that is, when building a cross-compiler), ++ the default value is 7. + The value can be followed by an option specifying how to implement floating point instructions. + Valid options are ,softfloat (default for 5) and ,hardfloat (default for 6 and 7). + GOARM64 +@@ -1029,7 +1034,7 @@ command + Example: Data + + If the server responds with any 4xx code, the go command will write the +- following to the programs' stdin: ++ following to the program's stdin: + Response = StatusLine { HeaderLine } BlankLine . + StatusLine = Protocol Space Status '\n' . + Protocol = /* HTTP protocol */ . +@@ -1097,7 +1102,7 @@ Furthermore, as with TestEvent, parsers can simply concatenate the Output + fields of all events to reconstruct the text format output, as it would + have appeared from go build without the -json flag. + +-Note that there may also be non-JSON error text on stdnard error, even ++Note that there may also be non-JSON error text on standard error, even + with the -json flag. Typically, this indicates an early, serious error. + Consumers should be robust to this. + `, +diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go +index df790e1eaa..15f6b2e87b 100644 +--- a/src/cmd/go/internal/load/pkg.go ++++ b/src/cmd/go/internal/load/pkg.go +@@ -3068,7 +3068,15 @@ func setPGOProfilePath(pkgs []*Package) { + // CheckPackageErrors prints errors encountered loading pkgs and their + // dependencies, then exits with a non-zero status if any errors were found. + func CheckPackageErrors(pkgs []*Package) { +- var anyIncomplete bool ++ PackageErrors(pkgs, func(p *Package) { ++ DefaultPrinter().Errorf(p, "%v", p.Error) ++ }) ++ base.ExitIfErrors() ++} ++ ++// PackageErrors calls report for errors encountered loading pkgs and their dependencies. ++func PackageErrors(pkgs []*Package, report func(*Package)) { ++ var anyIncomplete, anyErrors bool + for _, pkg := range pkgs { + if pkg.Incomplete { + anyIncomplete = true +@@ -3078,11 +3086,14 @@ func CheckPackageErrors(pkgs []*Package) { + all := PackageList(pkgs) + for _, p := range all { + if p.Error != nil { +- DefaultPrinter().Errorf(p, "%v", p.Error) ++ report(p) ++ anyErrors = true + } + } + } +- base.ExitIfErrors() ++ if anyErrors { ++ return ++ } + + // Check for duplicate loads of the same package. + // That should be impossible, but if it does happen then +@@ -3105,7 +3116,9 @@ func CheckPackageErrors(pkgs []*Package) { + } + seen[key] = true + } +- base.ExitIfErrors() ++ if len(reported) > 0 { ++ base.ExitIfErrors() ++ } + } + + // mainPackagesOnly filters out non-main packages matched only by arguments +diff --git a/src/cmd/go/internal/mmap/mmap.go b/src/cmd/go/internal/mmap/mmap.go +index fcbd3e08c1..fd374df82e 100644 +--- a/src/cmd/go/internal/mmap/mmap.go ++++ b/src/cmd/go/internal/mmap/mmap.go +@@ -22,10 +22,11 @@ type Data struct { + } + + // Mmap maps the given file into memory. +-func Mmap(file string) (Data, error) { ++func Mmap(file string) (Data, bool, error) { + f, err := os.Open(file) + if err != nil { +- return Data{}, err ++ return Data{}, false, err + } +- return mmapFile(f) ++ data, err := mmapFile(f) ++ return data, true, err + } +diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go +index 159a856911..48ae12fe53 100644 +--- a/src/cmd/go/internal/modget/get.go ++++ b/src/cmd/go/internal/modget/get.go +@@ -125,11 +125,6 @@ suggested Go toolchain, see https://go.dev/doc/toolchain. + + For more about specifying packages, see 'go help packages'. + +-This text describes the behavior of get using modules to manage source +-code and dependencies. If instead the go command is running in GOPATH +-mode, the details of get's flags and effects change, as does 'go help get'. +-See 'go help gopath-get'. +- + See also: go build, go install, go clean, go mod. + `, + } +diff --git a/src/cmd/go/internal/modindex/read.go b/src/cmd/go/internal/modindex/read.go +index c4102409b4..4c1fbd8359 100644 +--- a/src/cmd/go/internal/modindex/read.go ++++ b/src/cmd/go/internal/modindex/read.go +@@ -183,16 +183,21 @@ func openIndexModule(modroot string, ismodcache bool) (*Module, error) { + if err != nil { + return nil, err + } +- data, _, err := cache.GetMmap(cache.Default(), id) ++ data, _, opened, err := cache.GetMmap(cache.Default(), id) + if err != nil { + // Couldn't read from modindex. Assume we couldn't read from + // the index because the module hasn't been indexed yet. ++ // But double check on Windows that we haven't opened the file yet, ++ // because once mmap opens the file, we can't close it, and ++ // Windows won't let us open an already opened file. + data, err = indexModule(modroot) + if err != nil { + return nil, err + } +- if err = cache.PutBytes(cache.Default(), id, data); err != nil { +- return nil, err ++ if runtime.GOOS != "windows" || !opened { ++ if err = cache.PutBytes(cache.Default(), id, data); err != nil { ++ return nil, err ++ } + } + } + mi, err := fromBytes(modroot, data) +@@ -212,13 +217,18 @@ func openIndexPackage(modroot, pkgdir string) (*IndexPackage, error) { + if err != nil { + return nil, err + } +- data, _, err := cache.GetMmap(cache.Default(), id) ++ data, _, opened, err := cache.GetMmap(cache.Default(), id) + if err != nil { + // Couldn't read from index. Assume we couldn't read from + // the index because the package hasn't been indexed yet. ++ // But double check on Windows that we haven't opened the file yet, ++ // because once mmap opens the file, we can't close it, and ++ // Windows won't let us open an already opened file. + data = indexPackage(modroot, pkgdir) +- if err = cache.PutBytes(cache.Default(), id, data); err != nil { +- return nil, err ++ if runtime.GOOS != "windows" || !opened { ++ if err = cache.PutBytes(cache.Default(), id, data); err != nil { ++ return nil, err ++ } + } + } + pkg, err := packageFromBytes(modroot, data) +diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go +index 41ddb2f5d0..90f2d88d6b 100644 +--- a/src/cmd/go/internal/test/test.go ++++ b/src/cmd/go/internal/test/test.go +@@ -994,14 +994,15 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { + + // Prepare build + run + print actions for all packages being tested. + for _, p := range pkgs { +- buildTest, runTest, printTest, perr, err := builderTest(b, ctx, pkgOpts, p, allImports[p], writeCoverMetaAct) +- if err != nil { ++ reportErr := func(perr *load.Package, err error) { + str := err.Error() + if p.ImportPath != "" { + load.DefaultPrinter().Errorf(perr, "# %s\n%s", p.ImportPath, str) + } else { + load.DefaultPrinter().Errorf(perr, "%s", str) + } ++ } ++ reportSetupFailed := func(perr *load.Package, err error) { + var stdout io.Writer = os.Stdout + if testJSON { + json := test2json.NewConverter(stdout, p.ImportPath, test2json.Timestamp) +@@ -1009,11 +1010,34 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { + json.Exited(err) + json.Close() + }() +- json.SetFailedBuild(perr.Desc()) ++ if gotestjsonbuildtext.Value() == "1" { ++ // While this flag is about go build -json, the other effect ++ // of that change was to include "FailedBuild" in the test JSON. ++ gotestjsonbuildtext.IncNonDefault() ++ } else { ++ json.SetFailedBuild(perr.Desc()) ++ } + stdout = json + } + fmt.Fprintf(stdout, "FAIL\t%s [setup failed]\n", p.ImportPath) + base.SetExitStatus(1) ++ } ++ ++ var firstErrPkg *load.Package // arbitrarily report setup failed error for first error pkg reached in DFS ++ load.PackageErrors([]*load.Package{p}, func(p *load.Package) { ++ reportErr(p, p.Error) ++ if firstErrPkg == nil { ++ firstErrPkg = p ++ } ++ }) ++ if firstErrPkg != nil { ++ reportSetupFailed(firstErrPkg, firstErrPkg.Error) ++ continue ++ } ++ buildTest, runTest, printTest, perr, err := builderTest(b, ctx, pkgOpts, p, allImports[p], writeCoverMetaAct) ++ if err != nil { ++ reportErr(perr, err) ++ reportSetupFailed(perr, err) + continue + } + builds = append(builds, buildTest) +@@ -1437,7 +1461,11 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action) + if a.Failed != nil { + // We were unable to build the binary. + if json != nil && a.Failed.Package != nil { +- json.SetFailedBuild(a.Failed.Package.Desc()) ++ if gotestjsonbuildtext.Value() == "1" { ++ gotestjsonbuildtext.IncNonDefault() ++ } else { ++ json.SetFailedBuild(a.Failed.Package.Desc()) ++ } + } + a.Failed = nil + fmt.Fprintf(stdout, "FAIL\t%s [build failed]\n", a.Package.ImportPath) +diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go +index cbdd7a2418..aeab59519c 100644 +--- a/src/cmd/go/internal/toolchain/select.go ++++ b/src/cmd/go/internal/toolchain/select.go +@@ -169,7 +169,7 @@ func Select() { + } + + gotoolchain = minToolchain +- if (mode == "auto" || mode == "path") && !goInstallVersion() { ++ if (mode == "auto" || mode == "path") && !goInstallVersion(minVers) { + // Read go.mod to find new minimum and suggested toolchain. + file, goVers, toolchain := modGoToolchain() + gover.Startup.AutoFile = file +@@ -549,7 +549,7 @@ func modGoToolchain() (file, goVers, toolchain string) { + + // goInstallVersion reports whether the command line is go install m@v or go run m@v. + // If so, Select must not read the go.mod or go.work file in "auto" or "path" mode. +-func goInstallVersion() bool { ++func goInstallVersion(minVers string) bool { + // Note: We assume there are no flags between 'go' and 'install' or 'run'. + // During testing there are some debugging flags that are accepted + // in that position, but in production go binaries there are not. +@@ -708,7 +708,11 @@ func goInstallVersion() bool { + if errors.Is(err, gover.ErrTooNew) { + // Run early switch, same one go install or go run would eventually do, + // if it understood all the command-line flags. +- SwitchOrFatal(ctx, err) ++ var s Switcher ++ s.Error(err) ++ if s.TooNew != nil && gover.Compare(s.TooNew.GoVersion, minVers) > 0 { ++ SwitchOrFatal(ctx, err) ++ } + } + + return true // pkg@version found +diff --git a/src/cmd/go/internal/vcweb/auth.go b/src/cmd/go/internal/vcweb/auth.go +index 383bf759ff..e7c7c6ca26 100644 +--- a/src/cmd/go/internal/vcweb/auth.go ++++ b/src/cmd/go/internal/vcweb/auth.go +@@ -63,6 +63,7 @@ func (h *authHandler) Handler(dir string, env []string, logger *log.Logger) (htt + var err error + accessFile, err = fs.Open(path.Join(accessDir, ".access")) + if err == nil { ++ defer accessFile.Close() + break + } + +diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go +index 55b3190300..cab722c28a 100644 +--- a/src/cmd/go/internal/work/buildid.go ++++ b/src/cmd/go/internal/work/buildid.go +@@ -15,7 +15,6 @@ import ( + "cmd/go/internal/base" + "cmd/go/internal/cache" + "cmd/go/internal/cfg" +- "cmd/go/internal/fips140" + "cmd/go/internal/fsys" + "cmd/go/internal/str" + "cmd/internal/buildid" +@@ -447,19 +446,6 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string, + a.buildID = actionID + buildIDSeparator + mainpkg.buildID + buildIDSeparator + contentID + } + +- // In FIPS mode, we disable any link caching, +- // so that we always leave fips.o in $WORK/b001. +- // This makes sure that labs validating the FIPS +- // implementation can always run 'go build -work' +- // and then find fips.o in $WORK/b001/fips.o. +- // We could instead also save the fips.o and restore it +- // to $WORK/b001 from the cache, +- // but we went years without caching binaries anyway, +- // so not caching them for FIPS will be fine, at least to start. +- if a.Mode == "link" && fips140.Enabled() && a.Package != nil && !strings.HasSuffix(a.Package.ImportPath, ".test") { +- return false +- } +- + // If user requested -a, we force a rebuild, so don't use the cache. + if cfg.BuildA { + if p := a.Package; p != nil && !p.Stale { +@@ -519,7 +505,7 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string, + oldBuildID := a.buildID + a.buildID = id[1] + buildIDSeparator + id[2] + linkID := buildid.HashToString(b.linkActionID(a.triggers[0])) +- if id[0] == linkID && !fips140.Enabled() { ++ if id[0] == linkID { + // Best effort attempt to display output from the compile and link steps. + // If it doesn't work, it doesn't work: reusing the cached binary is more + // important than reprinting diagnostic information. +diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go +index 2538fae52f..7b073165d5 100644 +--- a/src/cmd/go/internal/work/exec.go ++++ b/src/cmd/go/internal/work/exec.go +@@ -1374,6 +1374,7 @@ func (b *Builder) linkActionID(a *Action) cache.ActionID { + fmt.Fprintf(h, "buildmode %s goos %s goarch %s\n", cfg.BuildBuildmode, cfg.Goos, cfg.Goarch) + fmt.Fprintf(h, "import %q\n", p.ImportPath) + fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix) ++ fmt.Fprintf(h, "defaultgodebug %q\n", p.DefaultGODEBUG) + if cfg.BuildTrimpath { + fmt.Fprintln(h, "trimpath") + } +diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go +index 1e2f81b2d4..33341a4f4d 100644 +--- a/src/cmd/go/internal/work/security.go ++++ b/src/cmd/go/internal/work/security.go +@@ -201,23 +201,23 @@ var validLinkerFlags = []*lazyregexp.Regexp{ + re(`-Wl,--end-group`), + re(`-Wl,--(no-)?export-dynamic`), + re(`-Wl,-E`), +- re(`-Wl,-framework,[^,@\-][^,]+`), ++ re(`-Wl,-framework,[^,@\-][^,]*`), + re(`-Wl,--hash-style=(sysv|gnu|both)`), + re(`-Wl,-headerpad_max_install_names`), + re(`-Wl,--no-undefined`), + re(`-Wl,--pop-state`), + re(`-Wl,--push-state`), + re(`-Wl,-R,?([^@\-,][^,@]*$)`), +- re(`-Wl,--just-symbols[=,]([^,@\-][^,@]+)`), +- re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]+)`), ++ re(`-Wl,--just-symbols[=,]([^,@\-][^,@]*)`), ++ re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]*)`), + re(`-Wl,-s`), + re(`-Wl,-search_paths_first`), +- re(`-Wl,-sectcreate,([^,@\-][^,]+),([^,@\-][^,]+),([^,@\-][^,]+)`), ++ re(`-Wl,-sectcreate,([^,@\-][^,]*),([^,@\-][^,]*),([^,@\-][^,]*)`), + re(`-Wl,--start-group`), + re(`-Wl,-?-static`), + re(`-Wl,-?-subsystem,(native|windows|console|posix|xbox)`), +- re(`-Wl,-syslibroot[=,]([^,@\-][^,]+)`), +- re(`-Wl,-undefined[=,]([^,@\-][^,]+)`), ++ re(`-Wl,-syslibroot[=,]([^,@\-][^,]*)`), ++ re(`-Wl,-undefined[=,]([^,@\-][^,]*)`), + re(`-Wl,-?-unresolved-symbols=[^,]+`), + re(`-Wl,--(no-)?warn-([^,]+)`), + re(`-Wl,-?-wrap[=,][^,@\-][^,]*`), +@@ -227,6 +227,21 @@ var validLinkerFlags = []*lazyregexp.Regexp{ + re(`\./.*\.(a|o|obj|dll|dylib|so|tbd)`), + } + ++var validLinkerFlagsOnDarwin = []*lazyregexp.Regexp{ ++ // The GNU linker interprets `@file` as "read command-line options from ++ // file". Thus, we forbid values starting with `@` on linker flags. ++ // However, this causes a problem when targeting Darwin. ++ // `@executable_path`, `@loader_path`, and `@rpath` are special values ++ // used in Mach-O to change the library search path and can be used in ++ // conjunction with the `-install_name` and `-rpath` linker flags. ++ // Since the GNU linker does not support Mach-O, targeting Darwin ++ // implies not using the GNU linker. Therefore, we allow @ in the linker ++ // flags if and only if cfg.Goos == "darwin" || cfg.Goos == "ios". ++ re(`-Wl,-dylib_install_name,@rpath(/[^,]*)?`), ++ re(`-Wl,-install_name,@rpath(/[^,]*)?`), ++ re(`-Wl,-rpath,@(executable_path|loader_path)(/[^,]*)?`), ++} ++ + var validLinkerFlagsWithNextArg = []string{ + "-arch", + "-F", +@@ -249,8 +264,13 @@ func checkCompilerFlags(name, source string, list []string) error { + } + + func checkLinkerFlags(name, source string, list []string) error { ++ validLinkerFlagsForPlatform := validLinkerFlags ++ if cfg.Goos == "darwin" || cfg.Goos == "ios" { ++ validLinkerFlagsForPlatform = append(validLinkerFlags, validLinkerFlagsOnDarwin...) ++ } ++ + checkOverrides := true +- return checkFlags(name, source, list, invalidLinkerFlags, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides) ++ return checkFlags(name, source, list, invalidLinkerFlags, validLinkerFlagsForPlatform, validLinkerFlagsWithNextArg, checkOverrides) + } + + // checkCompilerFlagsForInternalLink returns an error if 'list' +diff --git a/src/cmd/go/internal/work/security_test.go b/src/cmd/go/internal/work/security_test.go +index 63dd569f7d..52e54e25e4 100644 +--- a/src/cmd/go/internal/work/security_test.go ++++ b/src/cmd/go/internal/work/security_test.go +@@ -8,6 +8,8 @@ import ( + "os" + "strings" + "testing" ++ ++ "cmd/go/internal/cfg" + ) + + var goodCompilerFlags = [][]string{ +@@ -182,6 +184,13 @@ var goodLinkerFlags = [][]string{ + {"-Wl,--pop-state"}, + {"-Wl,--push-state,--as-needed"}, + {"-Wl,--push-state,--no-as-needed,-Bstatic"}, ++ {"-Wl,--just-symbols,."}, ++ {"-Wl,-framework,."}, ++ {"-Wl,-rpath,."}, ++ {"-Wl,-rpath-link,."}, ++ {"-Wl,-sectcreate,.,.,."}, ++ {"-Wl,-syslibroot,."}, ++ {"-Wl,-undefined,."}, + } + + var badLinkerFlags = [][]string{ +@@ -238,6 +247,8 @@ var badLinkerFlags = [][]string{ + {"-Wl,--hash-style=foo"}, + {"-x", "--c"}, + {"-x", "@obj"}, ++ {"-Wl,-dylib_install_name,@foo"}, ++ {"-Wl,-install_name,@foo"}, + {"-Wl,-rpath,@foo"}, + {"-Wl,-R,foo,bar"}, + {"-Wl,-R,@foo"}, +@@ -254,6 +265,21 @@ var badLinkerFlags = [][]string{ + {"./-Wl,--push-state,-R.c"}, + } + ++var goodLinkerFlagsOnDarwin = [][]string{ ++ {"-Wl,-dylib_install_name,@rpath"}, ++ {"-Wl,-dylib_install_name,@rpath/"}, ++ {"-Wl,-dylib_install_name,@rpath/foo"}, ++ {"-Wl,-install_name,@rpath"}, ++ {"-Wl,-install_name,@rpath/"}, ++ {"-Wl,-install_name,@rpath/foo"}, ++ {"-Wl,-rpath,@executable_path"}, ++ {"-Wl,-rpath,@executable_path/"}, ++ {"-Wl,-rpath,@executable_path/foo"}, ++ {"-Wl,-rpath,@loader_path"}, ++ {"-Wl,-rpath,@loader_path/"}, ++ {"-Wl,-rpath,@loader_path/foo"}, ++} ++ + func TestCheckLinkerFlags(t *testing.T) { + for _, f := range goodLinkerFlags { + if err := checkLinkerFlags("test", "test", f); err != nil { +@@ -265,6 +291,31 @@ func TestCheckLinkerFlags(t *testing.T) { + t.Errorf("missing error for %q", f) + } + } ++ ++ goos := cfg.Goos ++ ++ cfg.Goos = "darwin" ++ for _, f := range goodLinkerFlagsOnDarwin { ++ if err := checkLinkerFlags("test", "test", f); err != nil { ++ t.Errorf("unexpected error for %q: %v", f, err) ++ } ++ } ++ ++ cfg.Goos = "ios" ++ for _, f := range goodLinkerFlagsOnDarwin { ++ if err := checkLinkerFlags("test", "test", f); err != nil { ++ t.Errorf("unexpected error for %q: %v", f, err) ++ } ++ } ++ ++ cfg.Goos = "linux" ++ for _, f := range goodLinkerFlagsOnDarwin { ++ if err := checkLinkerFlags("test", "test", f); err == nil { ++ t.Errorf("missing error for %q", f) ++ } ++ } ++ ++ cfg.Goos = goos + } + + func TestCheckFlagAllowDisallow(t *testing.T) { +diff --git a/src/cmd/go/testdata/script/build_cacheprog_issue70848.txt b/src/cmd/go/testdata/script/build_cacheprog_issue70848.txt +new file mode 100644 +index 0000000000..194fd47d93 +--- /dev/null ++++ b/src/cmd/go/testdata/script/build_cacheprog_issue70848.txt +@@ -0,0 +1,27 @@ ++[short] skip 'builds go programs' ++ ++go build -o cacheprog$GOEXE cacheprog.go ++env GOCACHEPROG=$GOPATH/src/cacheprog$GOEXE ++ ++# This should not deadlock ++go build simple.go ++! stderr 'cacheprog closed' ++ ++-- simple.go -- ++package main ++ ++func main() {} ++-- cacheprog.go -- ++// This is a minimal GOCACHEPROG program that doesn't respond to close. ++package main ++ ++import ( ++ "encoding/json" ++ "os" ++) ++ ++func main() { ++ json.NewEncoder(os.Stdout).Encode(map[string][]string{"KnownCommands": {"close"}}) ++ var res struct{} ++ json.NewDecoder(os.Stdin).Decode(&res) ++} +\ No newline at end of file +diff --git a/src/cmd/go/testdata/script/build_version_stamping_git.txt b/src/cmd/go/testdata/script/build_version_stamping_git.txt +index ed07e00c7b..db804b3847 100644 +--- a/src/cmd/go/testdata/script/build_version_stamping_git.txt ++++ b/src/cmd/go/testdata/script/build_version_stamping_git.txt +@@ -51,7 +51,7 @@ go version -m example$GOEXE + stdout '\s+mod\s+example\s+v1.0.1\s+' + rm example$GOEXE + +-# Use tag+dirty when there are uncomitted changes present. ++# Use tag+dirty when there are uncommitted changes present. + cp $WORK/copy/README $WORK/repo/README + go build + go version -m example$GOEXE +@@ -82,7 +82,7 @@ go version -m example$GOEXE + stdout '\s+mod\s+example\s+v1.0.3-0.20220719150702-deaeab06f7fe\s+' + rm example$GOEXE + +-# Use pseudo+dirty when uncomitted changes are present. ++# Use pseudo+dirty when uncommitted changes are present. + mv README2 README3 + go build + go version -m example$GOEXE +diff --git a/src/cmd/go/testdata/script/env_changed.txt b/src/cmd/go/testdata/script/env_changed.txt +index f57f69bfd7..10db765407 100644 +--- a/src/cmd/go/testdata/script/env_changed.txt ++++ b/src/cmd/go/testdata/script/env_changed.txt +@@ -1,5 +1,8 @@ + # Test query for non-defaults in the env + ++# Go+BoringCrypto conflicts with GOFIPS140. ++[GOEXPERIMENT:boringcrypto] skip ++ + env GOROOT=./a + env GOTOOLCHAIN=local + env GOSUMDB=nodefault +diff --git a/src/cmd/go/testdata/script/env_gocacheprog.txt b/src/cmd/go/testdata/script/env_gocacheprog.txt +new file mode 100644 +index 0000000000..1547bf058c +--- /dev/null ++++ b/src/cmd/go/testdata/script/env_gocacheprog.txt +@@ -0,0 +1,42 @@ ++# GOCACHEPROG unset ++env GOCACHEPROG= ++ ++go env ++stdout 'GOCACHEPROG=''?''?' ++ ++go env -changed ++! stdout 'GOCACHEPROG' ++ ++go env -changed -json ++! stdout 'GOCACHEPROG' ++ ++# GOCACHEPROG set ++[short] skip 'compiles and runs a go program' ++ ++go build -o cacheprog$GOEXE cacheprog.go ++ ++env GOCACHEPROG=$GOPATH/src/cacheprog$GOEXE ++ ++go env ++stdout 'GOCACHEPROG=''?'$GOCACHEPROG'''?' ++ ++go env -changed ++stdout 'GOCACHEPROG=''?'$GOCACHEPROG'''?' ++ ++go env -changed -json ++stdout '"GOCACHEPROG": ".*cacheprog'$GOEXE'"' ++ ++-- cacheprog.go -- ++// This is a minimal GOCACHEPROG program that can't actually do anything but exit. ++package main ++ ++import ( ++ "encoding/json" ++ "os" ++) ++ ++func main() { ++ json.NewEncoder(os.Stdout).Encode(map[string][]string{"KnownCommands": {"close"}}) ++ var res struct{} ++ json.NewDecoder(os.Stdin).Decode(&res) ++} +\ No newline at end of file +diff --git a/src/cmd/go/testdata/script/fips.txt b/src/cmd/go/testdata/script/fips.txt +index fd791d3990..374902eb70 100644 +--- a/src/cmd/go/testdata/script/fips.txt ++++ b/src/cmd/go/testdata/script/fips.txt +@@ -1,3 +1,6 @@ ++# Go+BoringCrypto conflicts with GOFIPS140. ++[GOEXPERIMENT:boringcrypto] skip ++ + # list with GOFIPS140=off + env GOFIPS140=off + go list -f '{{.DefaultGODEBUG}}' +@@ -17,12 +20,12 @@ go build -x -o x.exe + go build -x -o x.exe + ! stderr link + +-# build with GOFIPS140=latest is NOT cached (need fipso) ++# build with GOFIPS140=latest is cached too + env GOFIPS140=latest + go build -x -o x.exe + stderr link.*-fipso + go build -x -o x.exe +-stderr link.*-fipso ++! stderr link.*-fipso + + # build test with GOFIPS140=off is cached + env GOFIPS140=off +@@ -38,8 +41,6 @@ stderr link.*-fipso + go test -x -c + ! stderr link + +- +- + -- go.mod -- + module m + -- x.go -- +diff --git a/src/cmd/go/testdata/script/fipssnap.txt b/src/cmd/go/testdata/script/fipssnap.txt +index 17a9d647a1..465f304c46 100644 +--- a/src/cmd/go/testdata/script/fipssnap.txt ++++ b/src/cmd/go/testdata/script/fipssnap.txt +@@ -7,6 +7,9 @@ env alias=inprocess + skip 'no snapshots yet' + env GOFIPS140=$snap + ++# Go+BoringCrypto conflicts with GOFIPS140. ++[GOEXPERIMENT:boringcrypto] skip ++ + # default GODEBUG includes fips140=on + go list -f '{{.DefaultGODEBUG}}' + stdout fips140=on +@@ -44,11 +47,11 @@ stdout crypto/internal/fips140/$snap/sha256 + + [short] skip + +-# build with GOFIPS140=snap is NOT cached (need fipso) ++# build with GOFIPS140=snap is cached + go build -x -o x.exe + stderr link.*-fipso + go build -x -o x.exe +-stderr link.*-fipso ++! stderr link.*-fipso + + # build test with GOFIPS140=snap is cached + go test -x -c +diff --git a/src/cmd/go/testdata/script/gotoolchain_local.txt b/src/cmd/go/testdata/script/gotoolchain_local.txt +index db7e082db9..8bece6ebd8 100644 +--- a/src/cmd/go/testdata/script/gotoolchain_local.txt ++++ b/src/cmd/go/testdata/script/gotoolchain_local.txt +@@ -197,6 +197,17 @@ go mod edit -go=1.501 -toolchain=none + go version + stdout go1.501 + ++# avoid two-step switch, first from install target requirement, then from GOTOOLCHAIN min ++# instead, just jump directly to GOTOOLCHAIN min ++env TESTGO_VERSION=go1.2.3 ++env GODEBUG=toolchaintrace=1 ++env GOTOOLCHAIN=go1.23.0+auto ++! go install rsc.io/fortune/nonexist@v0.0.1 ++! stderr 'switching to go1.22.9' ++stderr 'using go1.23.0' ++env GODEBUG= ++env GOTOOLCHAIN=auto ++ + # go install m@v and go run m@v should ignore go.mod and use m@v + env TESTGO_VERSION=go1.2.3 + go mod edit -go=1.999 -toolchain=go1.998 +diff --git a/src/cmd/go/testdata/script/mod_help.txt b/src/cmd/go/testdata/script/mod_help.txt +index b5cd30c521..7cb808ff23 100644 +--- a/src/cmd/go/testdata/script/mod_help.txt ++++ b/src/cmd/go/testdata/script/mod_help.txt +@@ -3,4 +3,4 @@ env GO111MODULE=on + # go help get shows usage for get + go help get + stdout 'usage: go get' +-stdout 'get using modules to manage source' +\ No newline at end of file ++stdout 'updates go.mod to require those versions' +diff --git a/src/cmd/go/testdata/script/test_flags.txt b/src/cmd/go/testdata/script/test_flags.txt +index 7adf4e273c..afef08840d 100644 +--- a/src/cmd/go/testdata/script/test_flags.txt ++++ b/src/cmd/go/testdata/script/test_flags.txt +@@ -15,8 +15,8 @@ stdout '\Aok\s+example.com/x\s+[0-9.s]+\n\z' + # Even though ./x looks like a package path, the real package should be + # the implicit '.'. + ! go test --answer=42 ./x +-stdout '^FAIL\t. \[build failed\]' +-stderr '^\.: no Go files in '$PWD'$' ++stdout '^FAIL\t. \[setup failed\]' ++stderr '^# \.\nno Go files in '$PWD'$' + + # However, *flags* that appear after unrecognized flags should still be + # interpreted as flags, under the (possibly-erroneous) assumption that +diff --git a/src/cmd/go/testdata/script/test_fuzz_context.txt b/src/cmd/go/testdata/script/test_fuzz_context.txt +new file mode 100644 +index 0000000000..a830684708 +--- /dev/null ++++ b/src/cmd/go/testdata/script/test_fuzz_context.txt +@@ -0,0 +1,47 @@ ++[!fuzz] skip ++[short] skip ++env GOCACHE=$WORK/cache ++ ++# Test fuzz.Context. ++go test -vet=off context_fuzz_test.go ++stdout ^ok ++! stdout FAIL ++ ++go test -vet=off -fuzz=Fuzz -fuzztime=1x context_fuzz_test.go ++stdout ok ++! stdout FAIL ++ ++-- context_fuzz_test.go -- ++package context_fuzz ++ ++import ( ++ "context" ++ "errors" ++ "testing" ++) ++ ++func Fuzz(f *testing.F) { ++ ctx := f.Context() ++ if err := ctx.Err(); err != nil { ++ f.Fatalf("expected non-canceled context, got %v", err) ++ } ++ ++ f.Fuzz(func(t *testing.T, data []byte) { ++ innerCtx := t.Context() ++ if err := innerCtx.Err(); err != nil { ++ t.Fatalf("expected inner test to not inherit canceled context, got %v", err) ++ } ++ ++ t.Cleanup(func() { ++ if !errors.Is(innerCtx.Err(), context.Canceled) { ++ t.Fatal("expected context of inner test to be canceled after its fuzz function finished") ++ } ++ }) ++ }) ++ ++ f.Cleanup(func() { ++ if !errors.Is(ctx.Err(), context.Canceled) { ++ f.Fatal("expected context canceled before cleanup") ++ } ++ }) ++} +diff --git a/src/cmd/go/testdata/script/test_json_build.txt b/src/cmd/go/testdata/script/test_json_build.txt +index a3f0c37923..df8863ae03 100644 +--- a/src/cmd/go/testdata/script/test_json_build.txt ++++ b/src/cmd/go/testdata/script/test_json_build.txt +@@ -40,6 +40,18 @@ stdout '"Action":"output","Package":"m/loaderror","Output":"FAIL\\tm/loaderror \ + stdout '"Action":"fail","Package":"m/loaderror","Elapsed":.*,"FailedBuild":"x"' + ! stderr '.' + ++# Test an import cycle loading error in a non test file. (#70820) ++! go test -json -o=$devnull ./cycle/p ++stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"# m/cycle/p\\n"' ++stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"package m/cycle/p\\n"' ++stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"\\timports m/cycle/q from p.go\\n"' ++stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"\\timports m/cycle/q from q.go: import cycle not allowed\\n"' ++stdout '"ImportPath":"m/cycle/q","Action":"build-fail"' ++stdout '"Action":"start","Package":"m/cycle/p"' ++stdout '"Action":"output","Package":"m/cycle/p","Output":"FAIL\\tm/cycle/p \[setup failed\]\\n"' ++stdout '"Action":"fail","Package":"m/cycle/p","Elapsed":.*,"FailedBuild":"m/cycle/q"' ++! stderr '.' ++ + # Test a vet error + ! go test -json -o=$devnull ./veterror + stdout '"ImportPath":"m/veterror \[m/veterror.test\]","Action":"build-output","Output":"# m/veterror\\n"' +@@ -58,8 +70,9 @@ stderr '# m/builderror \[m/builderror.test\]\n' + stderr 'builderror'${/}'main_test.go:3:11: undefined: y\n' + stdout '"Action":"start","Package":"m/builderror"' + stdout '"Action":"output","Package":"m/builderror","Output":"FAIL\\tm/builderror \[build failed\]\\n"' +-stdout '"Action":"fail","Package":"m/builderror","Elapsed":.*,"FailedBuild":"m/builderror \[m/builderror\.test\]"' +- ++stdout '"Action":"fail","Package":"m/builderror","Elapsed":[0-9.]+\}' ++# FailedBuild should NOT appear in the output in this mode. ++! stdout '"FailedBuild"' + + -- go.mod -- + module m +@@ -98,3 +111,13 @@ import ( + func TestVetError(t *testing.T) { + fmt.Printf("%s") + } ++-- cycle/p/p.go -- ++package p ++ ++import "m/cycle/q" ++-- cycle/q/q.go -- ++package q ++ ++import ( ++ "m/cycle/q" ++) +diff --git a/src/cmd/go/testdata/script/test_setup_error.txt b/src/cmd/go/testdata/script/test_setup_error.txt +index 2999067f2c..bf566d4621 100644 +--- a/src/cmd/go/testdata/script/test_setup_error.txt ++++ b/src/cmd/go/testdata/script/test_setup_error.txt +@@ -33,10 +33,23 @@ stderr '# m/t2/p\n.*package x is not in std' + stdout 'FAIL m/t2/p \[setup failed\]' + stdout 'ok m/t' + +-# Finally, this one is a build error, but produced by cmd/go directly ++# Test that an import cycle error is reported. Test for #70820 ++! go test -o=$devnull ./cycle/p ./t ++stderr '# m/cycle/p\n.*package m/cycle/p\n\timports m/cycle/p from p\.go: import cycle not allowed' ++stdout 'FAIL m/cycle/p \[setup failed\]' ++stdout 'ok m/t' ++ ++# Test that multiple errors for the same package under test are reported. ++! go test -o=$devnull ./cycle/q ./t ++stderr '# m/cycle/q\n.*package m/cycle/q\n\timports m/cycle/p from q\.go\n\timports m/cycle/p from p\.go: import cycle not allowed' ++stdout 'FAIL m/cycle/q \[setup failed\]' ++stdout 'ok m/t' ++ ++# Finally, this one is a non-import-cycle load error that ++# is produced for the package under test. + ! go test -o=$devnull . ./t +-stderr '^\.: no Go files in '$PWD'$' +-stdout 'FAIL . \[build failed\]' ++stderr '# \.\n.*no Go files in '$PWD'$' ++stdout 'FAIL . \[setup failed\]' + stdout 'ok m/t' + + -- go.mod -- +@@ -68,6 +81,17 @@ package p + package p + + import "m/bad" ++-- cycle/p/p.go -- ++package p ++ ++import "m/cycle/p" ++-- cycle/q/q.go -- ++package q ++ ++import ( ++ "m/bad" ++ "m/cycle/p" ++) + -- bad/bad.go -- + package bad + +diff --git a/src/cmd/internal/disasm/disasm.go b/src/cmd/internal/disasm/disasm.go +index c317effa90..3ae8989b38 100644 +--- a/src/cmd/internal/disasm/disasm.go ++++ b/src/cmd/internal/disasm/disasm.go +@@ -410,14 +410,16 @@ func disasm_ppc64(code []byte, pc uint64, lookup lookupFunc, byteOrder binary.By + func disasm_riscv64(code []byte, pc uint64, lookup lookupFunc, byteOrder binary.ByteOrder, gnuAsm bool) (string, int) { + inst, err := riscv64asm.Decode(code) + var text string ++ size := inst.Len + if err != nil || inst.Op == 0 { ++ size = 2 + text = "?" + } else if gnuAsm { + text = fmt.Sprintf("%-36s // %s", riscv64asm.GoSyntax(inst, pc, lookup, textReader{code, pc}), riscv64asm.GNUSyntax(inst)) + } else { + text = riscv64asm.GoSyntax(inst, pc, lookup, textReader{code, pc}) + } +- return text, 4 ++ return text, size + } + + func disasm_s390x(code []byte, pc uint64, lookup lookupFunc, _ binary.ByteOrder, gnuAsm bool) (string, int) { +diff --git a/src/cmd/internal/hash/hash.go b/src/cmd/internal/hash/hash.go +index 20edc72c20..a37368f50e 100644 +--- a/src/cmd/internal/hash/hash.go ++++ b/src/cmd/internal/hash/hash.go +@@ -5,22 +5,33 @@ + // Package hash implements hash functions used in the compiler toolchain. + package hash + ++// TODO(rsc): Delete the 16 and 20 forms and use 32 at all call sites. ++ + import ( +- "crypto/md5" +- "crypto/sha1" + "crypto/sha256" + "hash" + ) + + const ( +- // Size32 is the size of 32 bytes hash checksum. +- Size32 = sha256.Size +- // Size20 is the size of 20 bytes hash checksum. +- Size20 = sha1.Size +- // Size16 is the size of 16 bytes hash checksum. +- Size16 = md5.Size ++ // Size32 is the size of the 32-byte hash checksum. ++ Size32 = 32 ++ // Size20 is the size of the 20-byte hash checksum. ++ Size20 = 20 ++ // Size16 is the size of the 16-byte hash checksum. ++ Size16 = 16 + ) + ++type shortHash struct { ++ hash.Hash ++ n int ++} ++ ++func (h *shortHash) Sum(b []byte) []byte { ++ old := b ++ sum := h.Hash.Sum(b) ++ return sum[:len(old)+h.n] ++} ++ + // New32 returns a new [hash.Hash] computing the 32 bytes hash checksum. + func New32() hash.Hash { + h := sha256.New() +@@ -30,12 +41,12 @@ func New32() hash.Hash { + + // New20 returns a new [hash.Hash] computing the 20 bytes hash checksum. + func New20() hash.Hash { +- return sha1.New() ++ return &shortHash{New32(), 20} + } + + // New16 returns a new [hash.Hash] computing the 16 bytes hash checksum. + func New16() hash.Hash { +- return md5.New() ++ return &shortHash{New32(), 16} + } + + // Sum32 returns the 32 bytes checksum of the data. +@@ -47,10 +58,16 @@ func Sum32(data []byte) [Size32]byte { + + // Sum20 returns the 20 bytes checksum of the data. + func Sum20(data []byte) [Size20]byte { +- return sha1.Sum(data) ++ sum := Sum32(data) ++ var short [Size20]byte ++ copy(short[:], sum[4:]) ++ return short + } + + // Sum16 returns the 16 bytes checksum of the data. + func Sum16(data []byte) [Size16]byte { +- return md5.Sum(data) ++ sum := Sum32(data) ++ var short [Size16]byte ++ copy(short[:], sum[8:]) ++ return short + } +diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go +index 4feccf54f6..8872579050 100644 +--- a/src/cmd/internal/obj/sym.go ++++ b/src/cmd/internal/obj/sym.go +@@ -320,7 +320,7 @@ func (ctxt *Link) NumberSyms() { + // Assign special index for builtin symbols. + // Don't do it when linking against shared libraries, as the runtime + // may be in a different library. +- if i := goobj.BuiltinIdx(rs.Name, int(rs.ABI())); i != -1 { ++ if i := goobj.BuiltinIdx(rs.Name, int(rs.ABI())); i != -1 && !rs.IsLinkname() { + rs.PkgIdx = goobj.PkgIdxBuiltin + rs.SymIdx = int32(i) + rs.Set(AttrIndexed, true) +diff --git a/src/cmd/link/doc.go b/src/cmd/link/doc.go +index 9ec2c002f4..7b548f960f 100644 +--- a/src/cmd/link/doc.go ++++ b/src/cmd/link/doc.go +@@ -118,6 +118,7 @@ Flags: + Link with race detection libraries. + -s + Omit the symbol table and debug information. ++ Implies the -w flag, which can be negated with -w=0. + -tmpdir dir + Write temporary files to dir. + Temporary files are only used in external linking mode. +diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go +index b6eaf69ca4..a6b94a829f 100644 +--- a/src/cmd/link/internal/ld/data.go ++++ b/src/cmd/link/internal/ld/data.go +@@ -55,17 +55,31 @@ import ( + ) + + // isRuntimeDepPkg reports whether pkg is the runtime package or its dependency. ++// TODO: just compute from the runtime package, and remove this hardcoded list. + func isRuntimeDepPkg(pkg string) bool { + switch pkg { + case "runtime", +- "sync/atomic", // runtime may call to sync/atomic, due to go:linkname +- "internal/abi", // used by reflectcall (and maybe more) +- "internal/bytealg", // for IndexByte ++ "sync/atomic", // runtime may call to sync/atomic, due to go:linkname // TODO: this is not true? ++ "internal/abi", // used by reflectcall (and maybe more) ++ "internal/asan", ++ "internal/bytealg", // for IndexByte ++ "internal/byteorder", + "internal/chacha8rand", // for rand +- "internal/cpu": // for cpu features ++ "internal/coverage/rtcov", ++ "internal/cpu", // for cpu features ++ "internal/goarch", ++ "internal/godebugs", ++ "internal/goexperiment", ++ "internal/goos", ++ "internal/msan", ++ "internal/profilerecord", ++ "internal/race", ++ "internal/stringslite", ++ "unsafe": + return true + } +- return strings.HasPrefix(pkg, "runtime/internal/") && !strings.HasSuffix(pkg, "_test") ++ return (strings.HasPrefix(pkg, "runtime/internal/") || strings.HasPrefix(pkg, "internal/runtime/")) && ++ !strings.HasSuffix(pkg, "_test") + } + + // Estimate the max size needed to hold any new trampolines created for this function. This +@@ -410,6 +424,9 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { + // FIXME: It should be forbidden to have R_ADDR from a + // symbol which isn't in .data. However, as .text has the + // same address once loaded, this is possible. ++ // TODO: .text (including rodata) to .data relocation ++ // doesn't work correctly, so we should really disallow it. ++ // See also aixStaticDataBase in symtab.go and in runtime. + if ldr.SymSect(s).Seg == &Segdata { + Xcoffadddynrel(target, ldr, syms, s, r, ri) + } +diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go +index 14c0b687d8..b653e09a3c 100644 +--- a/src/cmd/link/internal/ld/dwarf.go ++++ b/src/cmd/link/internal/ld/dwarf.go +@@ -520,7 +520,7 @@ func (d *dwctxt) defgotype(gotype loader.Sym) loader.Sym { + d.linkctxt.Errorf(gotype, "dwarf: type name doesn't start with \"type:\"") + return d.mustFind("
- -- -") + } +- name := sn[5:] // could also decode from Type.string ++ name := sn[len("type:"):] // could also decode from Type.string + + sdie := d.find(name) + if sdie != 0 { +@@ -534,7 +534,7 @@ func (d *dwctxt) defgotype(gotype loader.Sym) loader.Sym { + + func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { + sn := d.ldr.SymName(gotype) +- name := sn[5:] // could also decode from Type.string ++ name := sn[len("type:"):] // could also decode from Type.string + tdata := d.ldr.Data(gotype) + if len(tdata) == 0 { + d.linkctxt.Errorf(gotype, "missing type") +diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go +index 8156f83a7a..b89a7802a2 100644 +--- a/src/cmd/link/internal/ld/symtab.go ++++ b/src/cmd/link/internal/ld/symtab.go +@@ -707,6 +707,17 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { + // except go:buildid which is generated late and not used by the program. + addRef("go:buildid") + } ++ if ctxt.IsAIX() { ++ // On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol ++ // does not work. See data.go:relocsym, case R_ADDR. ++ // Here we record the unrelocated address in aixStaticDataBase (it is ++ // unrelocated as it is in RODATA) so we can compute the delta at ++ // run time. ++ sb := ldr.CreateSymForUpdate("runtime.aixStaticDataBase", 0) ++ sb.SetSize(0) ++ sb.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0)) ++ sb.SetType(sym.SRODATA) ++ } + + // text section information + slice(textsectionmapSym, uint64(nsections)) +diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go +index 6fe895a840..e7cc30ab07 100644 +--- a/src/cmd/link/internal/loader/loader.go ++++ b/src/cmd/link/internal/loader/loader.go +@@ -2338,6 +2338,45 @@ var blockedLinknames = map[string][]string{ + "runtime.newcoro": {"iter"}, + // fips info + "go:fipsinfo": {"crypto/internal/fips140/check"}, ++ // New internal linknames in Go 1.24 ++ // Pushed from runtime ++ "crypto/internal/fips140.fatal": {"crypto/internal/fips140"}, ++ "crypto/internal/fips140.getIndicator": {"crypto/internal/fips140"}, ++ "crypto/internal/fips140.setIndicator": {"crypto/internal/fips140"}, ++ "crypto/internal/sysrand.fatal": {"crypto/internal/sysrand"}, ++ "crypto/rand.fatal": {"crypto/rand"}, ++ "internal/runtime/maps.errNilAssign": {"internal/runtime/maps"}, ++ "internal/runtime/maps.fatal": {"internal/runtime/maps"}, ++ "internal/runtime/maps.mapKeyError": {"internal/runtime/maps"}, ++ "internal/runtime/maps.newarray": {"internal/runtime/maps"}, ++ "internal/runtime/maps.newobject": {"internal/runtime/maps"}, ++ "internal/runtime/maps.typedmemclr": {"internal/runtime/maps"}, ++ "internal/runtime/maps.typedmemmove": {"internal/runtime/maps"}, ++ "internal/sync.fatal": {"internal/sync"}, ++ "internal/sync.runtime_canSpin": {"internal/sync"}, ++ "internal/sync.runtime_doSpin": {"internal/sync"}, ++ "internal/sync.runtime_nanotime": {"internal/sync"}, ++ "internal/sync.runtime_Semrelease": {"internal/sync"}, ++ "internal/sync.runtime_SemacquireMutex": {"internal/sync"}, ++ "internal/sync.throw": {"internal/sync"}, ++ "internal/synctest.Run": {"internal/synctest"}, ++ "internal/synctest.Wait": {"internal/synctest"}, ++ "internal/synctest.acquire": {"internal/synctest"}, ++ "internal/synctest.release": {"internal/synctest"}, ++ "internal/synctest.inBubble": {"internal/synctest"}, ++ "runtime.getStaticuint64s": {"reflect"}, ++ "sync.runtime_SemacquireWaitGroup": {"sync"}, ++ "time.runtimeNow": {"time"}, ++ "time.runtimeNano": {"time"}, ++ // Pushed to runtime from internal/runtime/maps ++ // (other map functions are already linknamed in Go 1.23) ++ "runtime.mapaccess1": {"runtime"}, ++ "runtime.mapaccess1_fast32": {"runtime"}, ++ "runtime.mapaccess1_fast64": {"runtime"}, ++ "runtime.mapaccess1_faststr": {"runtime"}, ++ "runtime.mapdelete_fast32": {"runtime"}, ++ "runtime.mapdelete_fast64": {"runtime"}, ++ "runtime.mapdelete_faststr": {"runtime"}, + } + + // check if a linkname reference to symbol s from pkg is allowed +diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go +index f23951416b..ab56b49e15 100644 +--- a/src/cmd/link/link_test.go ++++ b/src/cmd/link/link_test.go +@@ -1518,6 +1518,8 @@ func TestCheckLinkname(t *testing.T) { + {"coro_asm", false}, + // pull-only linkname is not ok + {"coro2.go", false}, ++ // pull linkname of a builtin symbol is not ok ++ {"builtin.go", false}, + // legacy bad linkname is ok, for now + {"fastrand.go", true}, + {"badlinkname.go", true}, +diff --git a/src/cmd/link/testdata/linkname/builtin.go b/src/cmd/link/testdata/linkname/builtin.go +new file mode 100644 +index 0000000000..a238c9b967 +--- /dev/null ++++ b/src/cmd/link/testdata/linkname/builtin.go +@@ -0,0 +1,17 @@ ++// Copyright 2024 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Linkname builtin symbols (that is not already linknamed, ++// e.g. mapaccess1) is not allowed. ++ ++package main ++ ++import "unsafe" ++ ++func main() { ++ mapaccess1(nil, nil, nil) ++} ++ ++//go:linkname mapaccess1 runtime.mapaccess1 ++func mapaccess1(t, m, k unsafe.Pointer) unsafe.Pointer +diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go +index f1450dcbd2..3860895a0a 100644 +--- a/src/cmd/vet/vet_test.go ++++ b/src/cmd/vet/vet_test.go +@@ -108,7 +108,7 @@ func TestVet(t *testing.T) { + // is a no-op for files whose version >= go1.22, so we use a + // go.mod file in the rangeloop directory to "downgrade". + // +- // TOOD(adonovan): delete when go1.21 goes away. ++ // TODO(adonovan): delete when go1.21 goes away. + t.Run("loopclosure", func(t *testing.T) { + cmd := testenv.Command(t, testenv.GoToolPath(t), "vet", "-vettool="+vetPath(t), ".") + cmd.Env = append(os.Environ(), "GOWORK=off") +diff --git a/src/context/context.go b/src/context/context.go +index db8bc69553..bef9e8aab0 100644 +--- a/src/context/context.go ++++ b/src/context/context.go +@@ -10,23 +10,25 @@ + // calls to servers should accept a Context. The chain of function + // calls between them must propagate the Context, optionally replacing + // it with a derived Context created using [WithCancel], [WithDeadline], +-// [WithTimeout], or [WithValue]. When a Context is canceled, all +-// Contexts derived from it are also canceled. ++// [WithTimeout], or [WithValue]. ++// ++// A Context may be canceled to indicate that work done on its behalf should stop. ++// A Context with a deadline is canceled after the deadline passes. ++// When a Context is canceled, all Contexts derived from it are also canceled. + // + // The [WithCancel], [WithDeadline], and [WithTimeout] functions take a + // Context (the parent) and return a derived Context (the child) and a +-// [CancelFunc]. Calling the CancelFunc cancels the child and its ++// [CancelFunc]. Calling the CancelFunc directly cancels the child and its + // children, removes the parent's reference to the child, and stops + // any associated timers. Failing to call the CancelFunc leaks the +-// child and its children until the parent is canceled or the timer +-// fires. The go vet tool checks that CancelFuncs are used on all +-// control-flow paths. ++// child and its children until the parent is canceled. The go vet tool ++// checks that CancelFuncs are used on all control-flow paths. + // +-// The [WithCancelCause] function returns a [CancelCauseFunc], which +-// takes an error and records it as the cancellation cause. Calling +-// [Cause] on the canceled context or any of its children retrieves +-// the cause. If no cause is specified, Cause(ctx) returns the same +-// value as ctx.Err(). ++// The [WithCancelCause], [WithDeadlineCause], and [WithTimeoutCause] functions ++// return a [CancelCauseFunc], which takes an error and records it as ++// the cancellation cause. Calling [Cause] on the canceled context ++// or any of its children retrieves the cause. If no cause is specified, ++// Cause(ctx) returns the same value as ctx.Err(). + // + // Programs that use Contexts should follow these rules to keep interfaces + // consistent across packages and enable static analysis tools to check context +@@ -107,8 +109,8 @@ type Context interface { + + // If Done is not yet closed, Err returns nil. + // If Done is closed, Err returns a non-nil error explaining why: +- // Canceled if the context was canceled +- // or DeadlineExceeded if the context's deadline passed. ++ // DeadlineExceeded if the context's deadline passed, ++ // or Canceled if the context was canceled for some other reason. + // After Err returns a non-nil error, successive calls to Err return the same error. + Err() error + +@@ -160,11 +162,12 @@ type Context interface { + Value(key any) any + } + +-// Canceled is the error returned by [Context.Err] when the context is canceled. ++// Canceled is the error returned by [Context.Err] when the context is canceled ++// for some reason other than its deadline passing. + var Canceled = errors.New("context canceled") + +-// DeadlineExceeded is the error returned by [Context.Err] when the context's +-// deadline passes. ++// DeadlineExceeded is the error returned by [Context.Err] when the context is canceled ++// due to its deadline passing. + var DeadlineExceeded error = deadlineExceededError{} + + type deadlineExceededError struct{} +@@ -296,9 +299,8 @@ func Cause(c Context) error { + return c.Err() + } + +-// AfterFunc arranges to call f in its own goroutine after ctx is done +-// (canceled or timed out). +-// If ctx is already done, AfterFunc calls f immediately in its own goroutine. ++// AfterFunc arranges to call f in its own goroutine after ctx is canceled. ++// If ctx is already canceled, AfterFunc calls f immediately in its own goroutine. + // + // Multiple calls to AfterFunc on a context operate independently; + // one does not replace another. +@@ -306,7 +308,7 @@ func Cause(c Context) error { + // Calling the returned stop function stops the association of ctx with f. + // It returns true if the call stopped f from being run. + // If stop returns false, +-// either the context is done and f has been started in its own goroutine; ++// either the context is canceled and f has been started in its own goroutine; + // or f was already stopped. + // The stop function does not wait for f to complete before returning. + // If the caller needs to know whether f is completed, +diff --git a/src/context/example_test.go b/src/context/example_test.go +index b597b09f16..be8cd8376e 100644 +--- a/src/context/example_test.go ++++ b/src/context/example_test.go +@@ -146,8 +146,8 @@ func ExampleAfterFunc_cond() { + defer stopf() + + // Since the wakeups are using Broadcast instead of Signal, this call to +- // Wait may unblock due to some other goroutine's context becoming done, +- // so to be sure that ctx is actually done we need to check it in a loop. ++ // Wait may unblock due to some other goroutine's context being canceled, ++ // so to be sure that ctx is actually canceled we need to check it in a loop. + for !conditionMet() { + cond.Wait() + if ctx.Err() != nil { +diff --git a/src/crypto/cipher/cbc.go b/src/crypto/cipher/cbc.go +index b4536aceb9..8e61406296 100644 +--- a/src/crypto/cipher/cbc.go ++++ b/src/crypto/cipher/cbc.go +@@ -15,6 +15,7 @@ import ( + "bytes" + "crypto/internal/fips140/aes" + "crypto/internal/fips140/alias" ++ "crypto/internal/fips140only" + "crypto/subtle" + ) + +@@ -53,6 +54,9 @@ func NewCBCEncrypter(b Block, iv []byte) BlockMode { + if b, ok := b.(*aes.Block); ok { + return aes.NewCBCEncrypter(b, [16]byte(iv)) + } ++ if fips140only.Enabled { ++ panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode") ++ } + if cbc, ok := b.(cbcEncAble); ok { + return cbc.NewCBCEncrypter(iv) + } +@@ -129,6 +133,9 @@ func NewCBCDecrypter(b Block, iv []byte) BlockMode { + if b, ok := b.(*aes.Block); ok { + return aes.NewCBCDecrypter(b, [16]byte(iv)) + } ++ if fips140only.Enabled { ++ panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode") ++ } + if cbc, ok := b.(cbcDecAble); ok { + return cbc.NewCBCDecrypter(iv) + } +diff --git a/src/crypto/cipher/ctr.go b/src/crypto/cipher/ctr.go +index c868635b8a..49512ca5dd 100644 +--- a/src/crypto/cipher/ctr.go ++++ b/src/crypto/cipher/ctr.go +@@ -16,6 +16,7 @@ import ( + "bytes" + "crypto/internal/fips140/aes" + "crypto/internal/fips140/alias" ++ "crypto/internal/fips140only" + "crypto/subtle" + ) + +@@ -41,6 +42,9 @@ func NewCTR(block Block, iv []byte) Stream { + if block, ok := block.(*aes.Block); ok { + return aesCtrWrapper{aes.NewCTR(block, iv)} + } ++ if fips140only.Enabled { ++ panic("crypto/cipher: use of CTR with non-AES ciphers is not allowed in FIPS 140-only mode") ++ } + if ctr, ok := block.(ctrAble); ok { + return ctr.NewCTR(iv) + } +diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go +index 77727aaf96..f682e6b1c6 100644 +--- a/src/crypto/ecdsa/ecdsa.go ++++ b/src/crypto/ecdsa/ecdsa.go +@@ -3,7 +3,7 @@ + // license that can be found in the LICENSE file. + + // Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as +-// defined in FIPS 186-5 and SEC 1, Version 2.0. ++// defined in [FIPS 186-5]. + // + // Signatures generated by this package are not deterministic, but entropy is + // mixed with the private key and the message, achieving the same level of +@@ -12,6 +12,8 @@ + // Operations involving private keys are implemented using constant-time + // algorithms, as long as an [elliptic.Curve] returned by [elliptic.P224], + // [elliptic.P256], [elliptic.P384], or [elliptic.P521] is used. ++// ++// [FIPS 186-5]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf + package ecdsa + + import ( +@@ -183,7 +185,7 @@ func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) { + } + + func generateFIPS[P ecdsa.Point[P]](curve elliptic.Curve, c *ecdsa.Curve[P], rand io.Reader) (*PrivateKey, error) { +- if fips140only.Enabled && fips140only.ApprovedRandomReader(rand) { ++ if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) { + return nil, errors.New("crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode") + } + privateKey, err := ecdsa.GenerateKey(c, rand) +diff --git a/src/crypto/fips140/fips140.go b/src/crypto/fips140/fips140.go +index 9fd8fe76e5..41d0d170cf 100644 +--- a/src/crypto/fips140/fips140.go ++++ b/src/crypto/fips140/fips140.go +@@ -26,7 +26,7 @@ func Enabled() bool { + if currentlyEnabled != fips140.Enabled { + panic("crypto/fips140: GODEBUG setting changed after program start") + } +- if fips140.Enabled && !check.Enabled() { ++ if fips140.Enabled && !check.Verified { + panic("crypto/fips140: FIPS 140-3 mode enabled, but integrity check didn't pass") + } + return fips140.Enabled +diff --git a/src/crypto/internal/boring/boring.go b/src/crypto/internal/boring/boring.go +index 90cf1edb75..6dfc6ed5f5 100644 +--- a/src/crypto/internal/boring/boring.go ++++ b/src/crypto/internal/boring/boring.go +@@ -16,6 +16,7 @@ import "C" + import ( + "crypto/internal/boring/sig" + _ "crypto/internal/boring/syso" ++ "crypto/internal/fips140" + "internal/stringslite" + "math/bits" + "unsafe" +@@ -31,6 +32,12 @@ func init() { + sig.BoringCrypto() + } + ++func init() { ++ if fips140.Enabled { ++ panic("boringcrypto: cannot use GODEBUG=fips140 with GOEXPERIMENT=boringcrypto") ++ } ++} ++ + // Unreachable marks code that should be unreachable + // when BoringCrypto is in use. It panics. + func Unreachable() { +diff --git a/src/crypto/internal/cryptotest/allocations.go b/src/crypto/internal/cryptotest/allocations.go +index 0194c2f89d..70055af70b 100644 +--- a/src/crypto/internal/cryptotest/allocations.go ++++ b/src/crypto/internal/cryptotest/allocations.go +@@ -32,6 +32,12 @@ func SkipTestAllocations(t *testing.T) { + t.Skip("skipping allocations test on plan9") + } + ++ // s390x deviates from other assembly implementations and is very hard to ++ // test due to the lack of LUCI builders. See #67307. ++ if runtime.GOARCH == "s390x" { ++ t.Skip("skipping allocations test on s390x") ++ } ++ + // Some APIs rely on inliner and devirtualization to allocate on the stack. + testenv.SkipIfOptimizationOff(t) + } +diff --git a/src/crypto/internal/fips140/aes/aes.go b/src/crypto/internal/fips140/aes/aes.go +index 739f1a3dbe..62f6919eda 100644 +--- a/src/crypto/internal/fips140/aes/aes.go ++++ b/src/crypto/internal/fips140/aes/aes.go +@@ -94,6 +94,8 @@ func newBlockExpanded(c *blockExpanded, key []byte) { + func (c *Block) BlockSize() int { return BlockSize } + + func (c *Block) Encrypt(dst, src []byte) { ++ // AES-ECB is not approved in FIPS 140-3 mode. ++ fips140.RecordNonApproved() + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } +@@ -103,11 +105,12 @@ func (c *Block) Encrypt(dst, src []byte) { + if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } +- fips140.RecordApproved() + encryptBlock(c, dst, src) + } + + func (c *Block) Decrypt(dst, src []byte) { ++ // AES-ECB is not approved in FIPS 140-3 mode. ++ fips140.RecordNonApproved() + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } +@@ -117,6 +120,12 @@ func (c *Block) Decrypt(dst, src []byte) { + if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } +- fips140.RecordApproved() + decryptBlock(c, dst, src) + } ++ ++// EncryptBlockInternal applies the AES encryption function to one block. ++// ++// It is an internal function meant only for the gcm package. ++func EncryptBlockInternal(c *Block, dst, src []byte) { ++ encryptBlock(c, dst, src) ++} +diff --git a/src/crypto/internal/fips140/aes/cbc.go b/src/crypto/internal/fips140/aes/cbc.go +index c7837b9d87..f92af23a2a 100644 +--- a/src/crypto/internal/fips140/aes/cbc.go ++++ b/src/crypto/internal/fips140/aes/cbc.go +@@ -50,7 +50,7 @@ func cryptBlocksEncGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) { + for len(src) > 0 { + // Write the xor to dst, then encrypt in place. + subtle.XORBytes(dst[:BlockSize], src[:BlockSize], iv) +- b.Encrypt(dst[:BlockSize], dst[:BlockSize]) ++ encryptBlock(b, dst[:BlockSize], dst[:BlockSize]) + + // Move to the next block with this block as the next iv. + iv = dst[:BlockSize] +@@ -111,7 +111,7 @@ func cryptBlocksDecGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) { + copy(civ[:], src[start:end]) + + for start >= 0 { +- b.Decrypt(dst[start:end], src[start:end]) ++ decryptBlock(b, dst[start:end], src[start:end]) + + if start > 0 { + subtle.XORBytes(dst[start:end], dst[start:end], src[prev:start]) +diff --git a/src/crypto/internal/fips140/aes/ctr.go b/src/crypto/internal/fips140/aes/ctr.go +index f612034d85..2b0ee44cdd 100644 +--- a/src/crypto/internal/fips140/aes/ctr.go ++++ b/src/crypto/internal/fips140/aes/ctr.go +@@ -132,7 +132,7 @@ func ctrBlocks(b *Block, dst, src []byte, ivlo, ivhi uint64) { + byteorder.BEPutUint64(buf[i:], ivhi) + byteorder.BEPutUint64(buf[i+8:], ivlo) + ivlo, ivhi = add128(ivlo, ivhi, 1) +- b.Encrypt(buf[i:], buf[i:]) ++ encryptBlock(b, buf[i:], buf[i:]) + } + // XOR into buf first, in case src and dst overlap (see above). + subtle.XORBytes(buf, src, buf) +diff --git a/src/crypto/internal/fips140/aes/gcm/cmac.go b/src/crypto/internal/fips140/aes/gcm/cmac.go +index e0a9dc43de..3a979a5c70 100644 +--- a/src/crypto/internal/fips140/aes/gcm/cmac.go ++++ b/src/crypto/internal/fips140/aes/gcm/cmac.go +@@ -28,7 +28,7 @@ func NewCMAC(b *aes.Block) *CMAC { + } + + func (c *CMAC) deriveSubkeys() { +- c.b.Encrypt(c.k1[:], c.k1[:]) ++ aes.EncryptBlockInternal(&c.b, c.k1[:], c.k1[:]) + msb := shiftLeft(&c.k1) + c.k1[len(c.k1)-1] ^= msb * 0b10000111 + +@@ -45,7 +45,7 @@ func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte { + // Special-cased as a single empty partial final block. + x = c.k2 + x[len(m)] ^= 0b10000000 +- c.b.Encrypt(x[:], x[:]) ++ aes.EncryptBlockInternal(&c.b, x[:], x[:]) + return x + } + for len(m) >= aes.BlockSize { +@@ -54,7 +54,7 @@ func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte { + // Final complete block. + subtle.XORBytes(x[:], c.k1[:], x[:]) + } +- c.b.Encrypt(x[:], x[:]) ++ aes.EncryptBlockInternal(&c.b, x[:], x[:]) + m = m[aes.BlockSize:] + } + if len(m) > 0 { +@@ -62,7 +62,7 @@ func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte { + subtle.XORBytes(x[:], m, x[:]) + subtle.XORBytes(x[:], c.k2[:], x[:]) + x[len(m)] ^= 0b10000000 +- c.b.Encrypt(x[:], x[:]) ++ aes.EncryptBlockInternal(&c.b, x[:], x[:]) + } + return x + } +diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_asm.go b/src/crypto/internal/fips140/aes/gcm/gcm_asm.go +index d513f77a2f..7924e457de 100644 +--- a/src/crypto/internal/fips140/aes/gcm/gcm_asm.go ++++ b/src/crypto/internal/fips140/aes/gcm/gcm_asm.go +@@ -81,7 +81,7 @@ func seal(out []byte, g *GCM, nonce, plaintext, data []byte) { + gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) + } + +- g.cipher.Encrypt(tagMask[:], counter[:]) ++ aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) + + var tagOut [gcmTagSize]byte + gcmAesData(&g.productTable, data, &tagOut) +@@ -114,7 +114,7 @@ func open(out []byte, g *GCM, nonce, ciphertext, data []byte) error { + gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) + } + +- g.cipher.Encrypt(tagMask[:], counter[:]) ++ aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) + + var expectedTag [gcmTagSize]byte + gcmAesData(&g.productTable, data, &expectedTag) +diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_generic.go b/src/crypto/internal/fips140/aes/gcm/gcm_generic.go +index 778392661d..385955ed77 100644 +--- a/src/crypto/internal/fips140/aes/gcm/gcm_generic.go ++++ b/src/crypto/internal/fips140/aes/gcm/gcm_generic.go +@@ -12,7 +12,7 @@ import ( + + func sealGeneric(out []byte, g *GCM, nonce, plaintext, additionalData []byte) { + var H, counter, tagMask [gcmBlockSize]byte +- g.cipher.Encrypt(H[:], H[:]) ++ aes.EncryptBlockInternal(&g.cipher, H[:], H[:]) + deriveCounterGeneric(&H, &counter, nonce) + gcmCounterCryptGeneric(&g.cipher, tagMask[:], tagMask[:], &counter) + +@@ -25,7 +25,7 @@ func sealGeneric(out []byte, g *GCM, nonce, plaintext, additionalData []byte) { + + func openGeneric(out []byte, g *GCM, nonce, ciphertext, additionalData []byte) error { + var H, counter, tagMask [gcmBlockSize]byte +- g.cipher.Encrypt(H[:], H[:]) ++ aes.EncryptBlockInternal(&g.cipher, H[:], H[:]) + deriveCounterGeneric(&H, &counter, nonce) + gcmCounterCryptGeneric(&g.cipher, tagMask[:], tagMask[:], &counter) + +@@ -70,7 +70,7 @@ func gcmCounterCryptGeneric(b *aes.Block, out, src []byte, counter *[gcmBlockSiz + var mask [gcmBlockSize]byte + + for len(src) >= gcmBlockSize { +- b.Encrypt(mask[:], counter[:]) ++ aes.EncryptBlockInternal(b, mask[:], counter[:]) + gcmInc32(counter) + + subtle.XORBytes(out, src, mask[:]) +@@ -79,7 +79,7 @@ func gcmCounterCryptGeneric(b *aes.Block, out, src []byte, counter *[gcmBlockSiz + } + + if len(src) > 0 { +- b.Encrypt(mask[:], counter[:]) ++ aes.EncryptBlockInternal(b, mask[:], counter[:]) + gcmInc32(counter) + subtle.XORBytes(out, src, mask[:]) + } +diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go b/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go +index 5084835e88..8d44c75745 100644 +--- a/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go ++++ b/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go +@@ -51,7 +51,7 @@ func initGCM(g *GCM) { + } + + hle := make([]byte, gcmBlockSize) +- g.cipher.Encrypt(hle, hle) ++ aes.EncryptBlockInternal(&g.cipher, hle, hle) + + // Reverse the bytes in each 8 byte chunk + // Load little endian, store big endian +@@ -133,7 +133,7 @@ func seal(out []byte, g *GCM, nonce, plaintext, data []byte) { + var counter, tagMask [gcmBlockSize]byte + deriveCounter(&counter, nonce, &g.productTable) + +- g.cipher.Encrypt(tagMask[:], counter[:]) ++ aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) + gcmInc32(&counter) + + counterCrypt(&g.cipher, out, plaintext, &counter) +@@ -151,7 +151,7 @@ func open(out []byte, g *GCM, nonce, ciphertext, data []byte) error { + var counter, tagMask [gcmBlockSize]byte + deriveCounter(&counter, nonce, &g.productTable) + +- g.cipher.Encrypt(tagMask[:], counter[:]) ++ aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) + gcmInc32(&counter) + + var expectedTag [gcmTagSize]byte +diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go b/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go +index 6d88e18240..526f3f9d4a 100644 +--- a/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go ++++ b/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go +@@ -55,7 +55,7 @@ func initGCM(g *GCM) { + return + } + // Note that hashKey is also used in the KMA codepath to hash large nonces. +- g.cipher.Encrypt(g.hashKey[:], g.hashKey[:]) ++ aes.EncryptBlockInternal(&g.cipher, g.hashKey[:], g.hashKey[:]) + } + + // ghashAsm uses the GHASH algorithm to hash data with the given key. The initial +@@ -115,7 +115,7 @@ func counterCrypt(g *GCM, dst, src []byte, cnt *[gcmBlockSize]byte) { + } + if len(src) > 0 { + var x [16]byte +- g.cipher.Encrypt(x[:], cnt[:]) ++ aes.EncryptBlockInternal(&g.cipher, x[:], cnt[:]) + for i := range src { + dst[i] = src[i] ^ x[i] + } +diff --git a/src/crypto/internal/fips140/check/asan.go b/src/crypto/internal/fips140/asan.go +similarity index 92% +rename from src/crypto/internal/fips140/check/asan.go +rename to src/crypto/internal/fips140/asan.go +index 2c78348354..af8f24df81 100644 +--- a/src/crypto/internal/fips140/check/asan.go ++++ b/src/crypto/internal/fips140/asan.go +@@ -4,6 +4,6 @@ + + //go:build asan + +-package check ++package fips140 + + const asanEnabled = true +diff --git a/src/crypto/internal/fips140/bigmod/nat.go b/src/crypto/internal/fips140/bigmod/nat.go +index 2f17f896b3..6757cccd02 100644 +--- a/src/crypto/internal/fips140/bigmod/nat.go ++++ b/src/crypto/internal/fips140/bigmod/nat.go +@@ -134,6 +134,13 @@ func (x *Nat) set(y *Nat) *Nat { + return x + } + ++// Bits returns x as a little-endian slice of uint. The length of the slice ++// matches the announced length of x. The result and x share the same underlying ++// array. ++func (x *Nat) Bits() []uint { ++ return x.limbs ++} ++ + // Bytes returns x as a zero-extended big-endian byte slice. The size of the + // slice will match the size of m. + // +@@ -1058,6 +1065,34 @@ func (out *Nat) ExpShortVarTime(x *Nat, e uint, m *Modulus) *Nat { + // + //go:norace + func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { ++ u, A, err := extendedGCD(a, m.nat) ++ if err != nil { ++ return x, false ++ } ++ if u.IsOne() == no { ++ return x, false ++ } ++ return x.set(A), true ++} ++ ++// GCDVarTime calculates x = GCD(a, b) where at least one of a or b is odd, and ++// both are non-zero. If GCDVarTime returns an error, x is not modified. ++// ++// The output will be resized to the size of the larger of a and b. ++func (x *Nat) GCDVarTime(a, b *Nat) (*Nat, error) { ++ u, _, err := extendedGCD(a, b) ++ if err != nil { ++ return nil, err ++ } ++ return x.set(u), nil ++} ++ ++// extendedGCD computes u and A such that a = GCD(a, m) and u = A*a - B*m. ++// ++// u will have the size of the larger of a and m, and A will have the size of m. ++// ++// It is an error if either a or m is zero, or if they are both even. ++func extendedGCD(a, m *Nat) (u, A *Nat, err error) { + // This is the extended binary GCD algorithm described in the Handbook of + // Applied Cryptography, Algorithm 14.61, adapted by BoringSSL to bound + // coefficients and avoid negative numbers. For more details and proof of +@@ -1068,7 +1103,7 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { + // 1. Negate [B] and [C] so they are positive. The invariant now involves a + // subtraction. + // 2. If step 2 (both [x] and [y] are even) runs, abort immediately. This +- // algorithm only cares about [x] and [y] relatively prime. ++ // case needs to be handled by the caller. + // 3. Subtract copies of [x] and [y] as needed in step 6 (both [u] and [v] + // are odd) so coefficients stay in bounds. + // 4. Replace the [u >= v] check with [u > v]. This changes the end +@@ -1082,21 +1117,21 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { + // + // Note this algorithm does not handle either input being zero. + +- if a.IsZero() == yes { +- return x, false ++ if a.IsZero() == yes || m.IsZero() == yes { ++ return nil, nil, errors.New("extendedGCD: a or m is zero") + } +- if a.IsOdd() == no && !m.odd { +- // a and m are not coprime, as they are both even. +- return x, false ++ if a.IsOdd() == no && m.IsOdd() == no { ++ return nil, nil, errors.New("extendedGCD: both a and m are even") + } + +- u := NewNat().set(a).ExpandFor(m) +- v := m.Nat() ++ size := max(len(a.limbs), len(m.limbs)) ++ u = NewNat().set(a).expand(size) ++ v := NewNat().set(m).expand(size) + +- A := NewNat().reset(len(m.nat.limbs)) ++ A = NewNat().reset(len(m.limbs)) + A.limbs[0] = 1 + B := NewNat().reset(len(a.limbs)) +- C := NewNat().reset(len(m.nat.limbs)) ++ C := NewNat().reset(len(m.limbs)) + D := NewNat().reset(len(a.limbs)) + D.limbs[0] = 1 + +@@ -1119,11 +1154,11 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { + if u.IsOdd() == yes && v.IsOdd() == yes { + if v.cmpGeq(u) == no { + u.sub(v) +- A.Add(C, m) ++ A.Add(C, &Modulus{nat: m}) + B.Add(D, &Modulus{nat: a}) + } else { + v.sub(u) +- C.Add(A, m) ++ C.Add(A, &Modulus{nat: m}) + D.Add(B, &Modulus{nat: a}) + } + } +@@ -1137,7 +1172,7 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { + if u.IsOdd() == no { + rshift1(u, 0) + if A.IsOdd() == yes || B.IsOdd() == yes { +- rshift1(A, A.add(m.nat)) ++ rshift1(A, A.add(m)) + rshift1(B, B.add(a)) + } else { + rshift1(A, 0) +@@ -1146,7 +1181,7 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { + } else { // v.IsOdd() == no + rshift1(v, 0) + if C.IsOdd() == yes || D.IsOdd() == yes { +- rshift1(C, C.add(m.nat)) ++ rshift1(C, C.add(m)) + rshift1(D, D.add(a)) + } else { + rshift1(C, 0) +@@ -1155,10 +1190,7 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { + } + + if v.IsZero() == yes { +- if u.IsOne() == no { +- return x, false +- } +- return x.set(A), true ++ return u, A, nil + } + } + } +@@ -1177,3 +1209,20 @@ func rshift1(a *Nat, carry uint) { + } + } + } ++ ++// DivShortVarTime calculates x = x / y and returns the remainder. ++// ++// It panics if y is zero. ++// ++//go:norace ++func (x *Nat) DivShortVarTime(y uint) uint { ++ if y == 0 { ++ panic("bigmod: division by zero") ++ } ++ ++ var r uint ++ for i := len(x.limbs) - 1; i >= 0; i-- { ++ x.limbs[i], r = bits.Div(r, x.limbs[i], y) ++ } ++ return r ++} +diff --git a/src/crypto/internal/fips140/boring.go b/src/crypto/internal/fips140/boring.go +new file mode 100644 +index 0000000000..d627bc6890 +--- /dev/null ++++ b/src/crypto/internal/fips140/boring.go +@@ -0,0 +1,10 @@ ++// Copyright 2024 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Keep in sync with notboring.go and crypto/internal/boring/boring.go. ++//go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan && cgo ++ ++package fips140 ++ ++const boringEnabled = true +diff --git a/src/crypto/internal/fips140/check/check.go b/src/crypto/internal/fips140/check/check.go +index ff61b80cb3..f8a5d7a41e 100644 +--- a/src/crypto/internal/fips140/check/check.go ++++ b/src/crypto/internal/fips140/check/check.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-// Package check implements the FIPS-140 load-time code+data verification. ++// Package check implements the FIPS 140 load-time code+data verification. + // Every FIPS package providing cryptographic functionality except hmac and sha256 + // must import crypto/internal/fips140/check, so that the verification happens + // before initialization of package global variables. +@@ -13,37 +13,18 @@ + package check + + import ( ++ "crypto/internal/fips140" + "crypto/internal/fips140/hmac" + "crypto/internal/fips140/sha256" + "crypto/internal/fips140deps/byteorder" + "crypto/internal/fips140deps/godebug" + "io" +- "runtime" + "unsafe" + ) + +-// Enabled reports whether verification was enabled. +-// If Enabled returns true, then verification succeeded, +-// because if it failed the binary would have panicked at init time. +-func Enabled() bool { +- return enabled +-} +- +-var enabled bool // set when verification is enabled +-var Verified bool // set when verification succeeds, for testing +- +-// Supported reports whether the current GOOS/GOARCH is Supported at all. +-func Supported() bool { +- // See cmd/internal/obj/fips.go's EnableFIPS for commentary. +- switch { +- case runtime.GOARCH == "wasm", +- runtime.GOOS == "windows" && runtime.GOARCH == "386", +- runtime.GOOS == "windows" && runtime.GOARCH == "arm", +- runtime.GOOS == "aix": +- return false +- } +- return true +-} ++// Verified is set when verification succeeded. It can be expected to always be ++// true when [fips140.Enabled] is true, or init would have panicked. ++var Verified bool + + // Linkinfo holds the go:fipsinfo symbol prepared by the linker. + // See cmd/link/internal/ld/fips.go for details. +@@ -71,32 +52,12 @@ const fipsMagic = " Go fipsinfo \xff\x00" + var zeroSum [32]byte + + func init() { +- v := godebug.Value("#fips140") +- enabled = v != "" && v != "off" +- if !enabled { ++ if !fips140.Enabled { + return + } + +- if asanEnabled { +- // ASAN disapproves of reading swaths of global memory below. +- // One option would be to expose runtime.asanunpoison through +- // crypto/internal/fips140deps and then call it to unpoison the range +- // before reading it, but it is unclear whether that would then cause +- // false negatives. For now, FIPS+ASAN doesn't need to work. +- // If this is made to work, also re-enable the test in check_test.go +- // and in cmd/dist/test.go. +- panic("fips140: cannot verify in asan mode") +- } +- +- switch v { +- case "on", "only", "debug": +- // ok +- default: +- panic("fips140: unknown GODEBUG setting fips140=" + v) +- } +- +- if !Supported() { +- panic("fips140: unavailable on " + runtime.GOOS + "-" + runtime.GOARCH) ++ if err := fips140.Supported(); err != nil { ++ panic("fips140: " + err.Error()) + } + + if Linkinfo.Magic[0] != 0xff || string(Linkinfo.Magic[1:]) != fipsMagic || Linkinfo.Sum == zeroSum { +@@ -132,7 +93,14 @@ func init() { + panic("fips140: verification mismatch") + } + +- if v == "debug" { ++ // "The temporary value(s) generated during the integrity test of the ++ // module’s software or firmware shall [05.10] be zeroised from the module ++ // upon completion of the integrity test" ++ clear(sum) ++ clear(nbuf[:]) ++ h.Reset() ++ ++ if godebug.Value("#fips140") == "debug" { + println("fips140: verified code+data") + } + +diff --git a/src/crypto/internal/fips140/drbg/rand.go b/src/crypto/internal/fips140/drbg/rand.go +index 967fb0673e..e7ab19a4cf 100644 +--- a/src/crypto/internal/fips140/drbg/rand.go ++++ b/src/crypto/internal/fips140/drbg/rand.go +@@ -13,8 +13,15 @@ import ( + "sync" + ) + +-var mu sync.Mutex +-var drbg *Counter ++var drbgs = sync.Pool{ ++ New: func() any { ++ var c *Counter ++ entropy.Depleted(func(seed *[48]byte) { ++ c = NewCounter(seed) ++ }) ++ return c ++ }, ++} + + // Read fills b with cryptographically secure random bytes. In FIPS mode, it + // uses an SP 800-90A Rev. 1 Deterministic Random Bit Generator (DRBG). +@@ -33,14 +40,8 @@ func Read(b []byte) { + additionalInput := new([SeedSize]byte) + sysrand.Read(additionalInput[:16]) + +- mu.Lock() +- defer mu.Unlock() +- +- if drbg == nil { +- entropy.Depleted(func(seed *[48]byte) { +- drbg = NewCounter(seed) +- }) +- } ++ drbg := drbgs.Get().(*Counter) ++ defer drbgs.Put(drbg) + + for len(b) > 0 { + size := min(len(b), maxRequestSize) +diff --git a/src/crypto/internal/fips140/drbg/rand_test.go b/src/crypto/internal/fips140/drbg/rand_test.go +new file mode 100644 +index 0000000000..945ebde933 +--- /dev/null ++++ b/src/crypto/internal/fips140/drbg/rand_test.go +@@ -0,0 +1,27 @@ ++// Copyright 2025 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package drbg ++ ++import ( ++ "crypto/internal/fips140" ++ "testing" ++) ++ ++func BenchmarkDBRG(b *testing.B) { ++ old := fips140.Enabled ++ defer func() { ++ fips140.Enabled = old ++ }() ++ fips140.Enabled = true ++ ++ const N = 64 ++ b.SetBytes(N) ++ b.RunParallel(func(pb *testing.PB) { ++ buf := make([]byte, N) ++ for pb.Next() { ++ Read(buf) ++ } ++ }) ++} +diff --git a/src/crypto/internal/fips140/ecdsa/ecdsa.go b/src/crypto/internal/fips140/ecdsa/ecdsa.go +index 9459b03de7..11389e8210 100644 +--- a/src/crypto/internal/fips140/ecdsa/ecdsa.go ++++ b/src/crypto/internal/fips140/ecdsa/ecdsa.go +@@ -21,7 +21,7 @@ import ( + + type PrivateKey struct { + pub PublicKey +- d []byte // bigmod.(*Nat).Bytes output (fixed length) ++ d []byte // bigmod.(*Nat).Bytes output (same length as the curve order) + } + + func (priv *PrivateKey) Bytes() []byte { +@@ -262,7 +262,7 @@ func randomPoint[P Point[P]](c *Curve[P], generate func([]byte) error) (k *bigmo + var testingOnlyRejectionSamplingLooped func() + + // Signature is an ECDSA signature, where r and s are represented as big-endian +-// fixed-length byte slices. ++// byte slices of the same length as the curve order. + type Signature struct { + R, S []byte + } +diff --git a/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go b/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go +index 01379f998f..271a35897f 100644 +--- a/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go ++++ b/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go +@@ -47,15 +47,34 @@ func canUseKDSA(c curveID) (functionCode uint64, blockSize int, ok bool) { + case p384: + return 2, 48, true + case p521: ++ // Note that the block size doesn't match the field size for P-521. + return 3, 80, true + } + return 0, 0, false // A mismatch + } + +-func hashToBytes[P Point[P]](c *Curve[P], dst, hash []byte) { ++func hashToBytes[P Point[P]](c *Curve[P], hash []byte) []byte { + e := bigmod.NewNat() + hashToNat(c, e, hash) +- copy(dst, e.Bytes(c.N)) ++ return e.Bytes(c.N) ++} ++ ++func appendBlock(p []byte, blocksize int, b []byte) []byte { ++ if len(b) > blocksize { ++ panic("ecdsa: internal error: appendBlock input larger than block") ++ } ++ padding := blocksize - len(b) ++ p = append(p, make([]byte, padding)...) ++ return append(p, b...) ++} ++ ++func trimBlock(p []byte, size int) ([]byte, error) { ++ for _, b := range p[:len(p)-size] { ++ if b != 0 { ++ return nil, errors.New("ecdsa: internal error: KDSA produced invalid signature") ++ } ++ } ++ return p[len(p)-size:], nil + } + + func sign[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte) (*Signature, error) { +@@ -95,17 +114,27 @@ func sign[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte + + // Copy content into the parameter block. In the sign case, + // we copy hashed message, private key and random number into +- // the parameter block. +- hashToBytes(c, params[2*blockSize:3*blockSize], hash) +- copy(params[3*blockSize+blockSize-len(priv.d):], priv.d) +- copy(params[4*blockSize:5*blockSize], k.Bytes(c.N)) ++ // the parameter block. We skip the signature slots. ++ p := params[:2*blockSize] ++ p = appendBlock(p, blockSize, hashToBytes(c, hash)) ++ p = appendBlock(p, blockSize, priv.d) ++ p = appendBlock(p, blockSize, k.Bytes(c.N)) + // Convert verify function code into a sign function code by adding 8. + // We also need to set the 'deterministic' bit in the function code, by + // adding 128, in order to stop the instruction using its own random number + // generator in addition to the random number we supply. + switch kdsa(functionCode+136, ¶ms) { + case 0: // success +- return &Signature{R: params[:blockSize], S: params[blockSize : 2*blockSize]}, nil ++ elementSize := (c.N.BitLen() + 7) / 8 ++ r, err := trimBlock(params[:blockSize], elementSize) ++ if err != nil { ++ return nil, err ++ } ++ s, err := trimBlock(params[blockSize:2*blockSize], elementSize) ++ if err != nil { ++ return nil, err ++ } ++ return &Signature{R: r, S: s}, nil + case 1: // error + return nil, errors.New("zero parameter") + case 2: // retry +@@ -149,10 +178,12 @@ func verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature + // Copy content into the parameter block. In the verify case, + // we copy signature (r), signature(s), hashed message, public key x component, + // and public key y component into the parameter block. +- copy(params[0*blockSize+blockSize-len(r):], r) +- copy(params[1*blockSize+blockSize-len(s):], s) +- hashToBytes(c, params[2*blockSize:3*blockSize], hash) +- copy(params[3*blockSize:5*blockSize], pub.q[1:]) // strip 0x04 prefix ++ p := params[:0] ++ p = appendBlock(p, blockSize, r) ++ p = appendBlock(p, blockSize, s) ++ p = appendBlock(p, blockSize, hashToBytes(c, hash)) ++ p = appendBlock(p, blockSize, pub.q[1:1+len(pub.q)/2]) ++ p = appendBlock(p, blockSize, pub.q[1+len(pub.q)/2:]) + if kdsa(functionCode, ¶ms) != 0 { + return errors.New("invalid signature") + } +diff --git a/src/crypto/internal/fips140/fips140.go b/src/crypto/internal/fips140/fips140.go +index cec9d13e35..c7b167b82a 100644 +--- a/src/crypto/internal/fips140/fips140.go ++++ b/src/crypto/internal/fips140/fips140.go +@@ -4,18 +4,64 @@ + + package fips140 + +-import "crypto/internal/fips140deps/godebug" ++import ( ++ "crypto/internal/fips140deps/godebug" ++ "errors" ++ "runtime" ++) + + var Enabled bool + + var debug bool + + func init() { +- switch godebug.Value("#fips140") { ++ v := godebug.Value("#fips140") ++ switch v { + case "on", "only": + Enabled = true + case "debug": + Enabled = true + debug = true ++ case "off", "": ++ default: ++ panic("fips140: unknown GODEBUG setting fips140=" + v) + } + } ++ ++// Supported returns an error if FIPS 140-3 mode can't be enabled. ++func Supported() error { ++ // Keep this in sync with fipsSupported in cmd/dist/test.go. ++ ++ // ASAN disapproves of reading swaths of global memory in fips140/check. ++ // One option would be to expose runtime.asanunpoison through ++ // crypto/internal/fips140deps and then call it to unpoison the range ++ // before reading it, but it is unclear whether that would then cause ++ // false negatives. For now, FIPS+ASAN doesn't need to work. ++ if asanEnabled { ++ return errors.New("FIPS 140-3 mode is incompatible with ASAN") ++ } ++ ++ // See EnableFIPS in cmd/internal/obj/fips.go for commentary. ++ switch { ++ case runtime.GOARCH == "wasm", ++ runtime.GOOS == "windows" && runtime.GOARCH == "386", ++ runtime.GOOS == "windows" && runtime.GOARCH == "arm", ++ runtime.GOOS == "openbsd", // due to -fexecute-only, see #70880 ++ runtime.GOOS == "aix": ++ return errors.New("FIPS 140-3 mode is not supported on " + runtime.GOOS + "-" + runtime.GOARCH) ++ } ++ ++ if boringEnabled { ++ return errors.New("FIPS 140-3 mode is incompatible with GOEXPERIMENT=boringcrypto") ++ } ++ ++ return nil ++} ++ ++func Name() string { ++ return "Go Cryptographic Module" ++} ++ ++func Version() string { ++ return "v1.0" ++} +diff --git a/src/crypto/internal/fips140/mlkem/cast.go b/src/crypto/internal/fips140/mlkem/cast.go +index d3ae84ec3f..a432d1fdab 100644 +--- a/src/crypto/internal/fips140/mlkem/cast.go ++++ b/src/crypto/internal/fips140/mlkem/cast.go +@@ -40,7 +40,7 @@ func init() { + dk := &DecapsulationKey768{} + kemKeyGen(dk, d, z) + ek := dk.EncapsulationKey() +- c, Ke := ek.EncapsulateInternal(m) ++ Ke, c := ek.EncapsulateInternal(m) + Kd, err := dk.Decapsulate(c) + if err != nil { + return err +diff --git a/src/crypto/internal/fips140/mlkem/mlkem1024.go b/src/crypto/internal/fips140/mlkem/mlkem1024.go +index 5aa3c69243..c924c38293 100644 +--- a/src/crypto/internal/fips140/mlkem/mlkem1024.go ++++ b/src/crypto/internal/fips140/mlkem/mlkem1024.go +@@ -189,7 +189,7 @@ func kemKeyGen1024(dk *DecapsulationKey1024, d, z *[32]byte) { + // the first operational use (if not exported before the first use)." + func kemPCT1024(dk *DecapsulationKey1024) error { + ek := dk.EncapsulationKey() +- c, K := ek.Encapsulate() ++ K, c := ek.Encapsulate() + K1, err := dk.Decapsulate(c) + if err != nil { + return err +@@ -204,13 +204,13 @@ func kemPCT1024(dk *DecapsulationKey1024) error { + // encapsulation key, drawing random bytes from a DRBG. + // + // The shared key must be kept secret. +-func (ek *EncapsulationKey1024) Encapsulate() (ciphertext, sharedKey []byte) { ++func (ek *EncapsulationKey1024) Encapsulate() (sharedKey, ciphertext []byte) { + // The actual logic is in a separate function to outline this allocation. + var cc [CiphertextSize1024]byte + return ek.encapsulate(&cc) + } + +-func (ek *EncapsulationKey1024) encapsulate(cc *[CiphertextSize1024]byte) (ciphertext, sharedKey []byte) { ++func (ek *EncapsulationKey1024) encapsulate(cc *[CiphertextSize1024]byte) (sharedKey, ciphertext []byte) { + var m [messageSize]byte + drbg.Read(m[:]) + // Note that the modulus check (step 2 of the encapsulation key check from +@@ -221,7 +221,7 @@ func (ek *EncapsulationKey1024) encapsulate(cc *[CiphertextSize1024]byte) (ciphe + + // EncapsulateInternal is a derandomized version of Encapsulate, exclusively for + // use in tests. +-func (ek *EncapsulationKey1024) EncapsulateInternal(m *[32]byte) (ciphertext, sharedKey []byte) { ++func (ek *EncapsulationKey1024) EncapsulateInternal(m *[32]byte) (sharedKey, ciphertext []byte) { + cc := &[CiphertextSize1024]byte{} + return kemEncaps1024(cc, ek, m) + } +@@ -229,14 +229,14 @@ func (ek *EncapsulationKey1024) EncapsulateInternal(m *[32]byte) (ciphertext, sh + // kemEncaps1024 generates a shared key and an associated ciphertext. + // + // It implements ML-KEM.Encaps_internal according to FIPS 203, Algorithm 17. +-func kemEncaps1024(cc *[CiphertextSize1024]byte, ek *EncapsulationKey1024, m *[messageSize]byte) (c, K []byte) { ++func kemEncaps1024(cc *[CiphertextSize1024]byte, ek *EncapsulationKey1024, m *[messageSize]byte) (K, c []byte) { + g := sha3.New512() + g.Write(m[:]) + g.Write(ek.h[:]) + G := g.Sum(nil) + K, r := G[:SharedKeySize], G[SharedKeySize:] + c = pkeEncrypt1024(cc, &ek.encryptionKey1024, m, r) +- return c, K ++ return K, c + } + + // NewEncapsulationKey1024 parses an encapsulation key from its encoded form. +diff --git a/src/crypto/internal/fips140/mlkem/mlkem768.go b/src/crypto/internal/fips140/mlkem/mlkem768.go +index 0c91ceadc4..2c1cb5c33f 100644 +--- a/src/crypto/internal/fips140/mlkem/mlkem768.go ++++ b/src/crypto/internal/fips140/mlkem/mlkem768.go +@@ -246,7 +246,7 @@ func kemKeyGen(dk *DecapsulationKey768, d, z *[32]byte) { + // the first operational use (if not exported before the first use)." + func kemPCT(dk *DecapsulationKey768) error { + ek := dk.EncapsulationKey() +- c, K := ek.Encapsulate() ++ K, c := ek.Encapsulate() + K1, err := dk.Decapsulate(c) + if err != nil { + return err +@@ -261,13 +261,13 @@ func kemPCT(dk *DecapsulationKey768) error { + // encapsulation key, drawing random bytes from a DRBG. + // + // The shared key must be kept secret. +-func (ek *EncapsulationKey768) Encapsulate() (ciphertext, sharedKey []byte) { ++func (ek *EncapsulationKey768) Encapsulate() (sharedKey, ciphertext []byte) { + // The actual logic is in a separate function to outline this allocation. + var cc [CiphertextSize768]byte + return ek.encapsulate(&cc) + } + +-func (ek *EncapsulationKey768) encapsulate(cc *[CiphertextSize768]byte) (ciphertext, sharedKey []byte) { ++func (ek *EncapsulationKey768) encapsulate(cc *[CiphertextSize768]byte) (sharedKey, ciphertext []byte) { + var m [messageSize]byte + drbg.Read(m[:]) + // Note that the modulus check (step 2 of the encapsulation key check from +@@ -278,7 +278,7 @@ func (ek *EncapsulationKey768) encapsulate(cc *[CiphertextSize768]byte) (ciphert + + // EncapsulateInternal is a derandomized version of Encapsulate, exclusively for + // use in tests. +-func (ek *EncapsulationKey768) EncapsulateInternal(m *[32]byte) (ciphertext, sharedKey []byte) { ++func (ek *EncapsulationKey768) EncapsulateInternal(m *[32]byte) (sharedKey, ciphertext []byte) { + cc := &[CiphertextSize768]byte{} + return kemEncaps(cc, ek, m) + } +@@ -286,14 +286,14 @@ func (ek *EncapsulationKey768) EncapsulateInternal(m *[32]byte) (ciphertext, sha + // kemEncaps generates a shared key and an associated ciphertext. + // + // It implements ML-KEM.Encaps_internal according to FIPS 203, Algorithm 17. +-func kemEncaps(cc *[CiphertextSize768]byte, ek *EncapsulationKey768, m *[messageSize]byte) (c, K []byte) { ++func kemEncaps(cc *[CiphertextSize768]byte, ek *EncapsulationKey768, m *[messageSize]byte) (K, c []byte) { + g := sha3.New512() + g.Write(m[:]) + g.Write(ek.h[:]) + G := g.Sum(nil) + K, r := G[:SharedKeySize], G[SharedKeySize:] + c = pkeEncrypt(cc, &ek.encryptionKey, m, r) +- return c, K ++ return K, c + } + + // NewEncapsulationKey768 parses an encapsulation key from its encoded form. +diff --git a/src/crypto/internal/fips140/check/noasan.go b/src/crypto/internal/fips140/notasan.go +similarity index 92% +rename from src/crypto/internal/fips140/check/noasan.go +rename to src/crypto/internal/fips140/notasan.go +index 876d726f98..639d419ef9 100644 +--- a/src/crypto/internal/fips140/check/noasan.go ++++ b/src/crypto/internal/fips140/notasan.go +@@ -4,6 +4,6 @@ + + //go:build !asan + +-package check ++package fips140 + + const asanEnabled = false +diff --git a/src/crypto/internal/fips140/notboring.go b/src/crypto/internal/fips140/notboring.go +new file mode 100644 +index 0000000000..681521c687 +--- /dev/null ++++ b/src/crypto/internal/fips140/notboring.go +@@ -0,0 +1,9 @@ ++// Copyright 2024 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !(boringcrypto && linux && (amd64 || arm64) && !android && !msan && cgo) ++ ++package fips140 ++ ++const boringEnabled = false +diff --git a/src/crypto/internal/fips140/rsa/keygen.go b/src/crypto/internal/fips140/rsa/keygen.go +index df76772ef5..658eb9ab24 100644 +--- a/src/crypto/internal/fips140/rsa/keygen.go ++++ b/src/crypto/internal/fips140/rsa/keygen.go +@@ -13,9 +13,9 @@ import ( + ) + + // GenerateKey generates a new RSA key pair of the given bit size. +-// bits must be at least 128. ++// bits must be at least 32. + func GenerateKey(rand io.Reader, bits int) (*PrivateKey, error) { +- if bits < 128 { ++ if bits < 32 { + return nil, errors.New("rsa: key too small") + } + fips140.RecordApproved() +@@ -54,23 +54,42 @@ func GenerateKey(rand io.Reader, bits int) (*PrivateKey, error) { + return nil, errors.New("rsa: internal error: modulus size incorrect") + } + +- φ, err := bigmod.NewModulusProduct(P.Nat().SubOne(P).Bytes(P), +- Q.Nat().SubOne(Q).Bytes(Q)) ++ // d can be safely computed as e⁻¹ mod φ(N) where φ(N) = (p-1)(q-1), and ++ // indeed that's what both the original RSA paper and the pre-FIPS ++ // crypto/rsa implementation did. ++ // ++ // However, FIPS 186-5, A.1.1(3) requires computing it as e⁻¹ mod λ(N) ++ // where λ(N) = lcm(p-1, q-1). ++ // ++ // This makes d smaller by 1.5 bits on average, which is irrelevant both ++ // because we exclusively use the CRT for private operations and because ++ // we use constant time windowed exponentiation. On the other hand, it ++ // requires computing a GCD of two values that are not coprime, and then ++ // a division, both complex variable-time operations. ++ λ, err := totient(P, Q) ++ if err == errDivisorTooLarge { ++ // The divisor is too large, try again with different primes. ++ continue ++ } + if err != nil { + return nil, err + } + + e := bigmod.NewNat().SetUint(65537) +- d, ok := bigmod.NewNat().InverseVarTime(e, φ) ++ d, ok := bigmod.NewNat().InverseVarTime(e, λ) + if !ok { +- // This checks that GCD(e, (p-1)(q-1)) = 1, which is equivalent ++ // This checks that GCD(e, lcm(p-1, q-1)) = 1, which is equivalent + // to checking GCD(e, p-1) = 1 and GCD(e, q-1) = 1 separately in + // FIPS 186-5, Appendix A.1.3, steps 4.5 and 5.6. ++ // ++ // We waste a prime by retrying the whole process, since 65537 is ++ // probably only a factor of one of p-1 or q-1, but the probability ++ // of this check failing is only 1/65537, so it doesn't matter. + continue + } + +- if e.ExpandFor(φ).Mul(d, φ).IsOne() == 0 { +- return nil, errors.New("rsa: internal error: e*d != 1 mod φ(N)") ++ if e.ExpandFor(λ).Mul(d, λ).IsOne() == 0 { ++ return nil, errors.New("rsa: internal error: e*d != 1 mod λ(N)") + } + + // FIPS 186-5, A.1.1(3) requires checking that d > 2^(nlen / 2). +@@ -90,11 +109,57 @@ func GenerateKey(rand io.Reader, bits int) (*PrivateKey, error) { + } + } + ++// errDivisorTooLarge is returned by [totient] when gcd(p-1, q-1) is too large. ++var errDivisorTooLarge = errors.New("divisor too large") ++ ++// totient computes the Carmichael totient function λ(N) = lcm(p-1, q-1). ++func totient(p, q *bigmod.Modulus) (*bigmod.Modulus, error) { ++ a, b := p.Nat().SubOne(p), q.Nat().SubOne(q) ++ ++ // lcm(a, b) = a×b / gcd(a, b) = a × (b / gcd(a, b)) ++ ++ // Our GCD requires at least one of the numbers to be odd. For LCM we only ++ // need to preserve the larger prime power of each prime factor, so we can ++ // right-shift the number with the fewest trailing zeros until it's odd. ++ // For odd a, b and m >= n, lcm(a×2ᵐ, b×2ⁿ) = lcm(a×2ᵐ, b). ++ az, bz := a.TrailingZeroBitsVarTime(), b.TrailingZeroBitsVarTime() ++ if az < bz { ++ a = a.ShiftRightVarTime(az) ++ } else { ++ b = b.ShiftRightVarTime(bz) ++ } ++ ++ gcd, err := bigmod.NewNat().GCDVarTime(a, b) ++ if err != nil { ++ return nil, err ++ } ++ if gcd.IsOdd() == 0 { ++ return nil, errors.New("rsa: internal error: gcd(a, b) is even") ++ } ++ ++ // To avoid implementing multiple-precision division, we just try again if ++ // the divisor doesn't fit in a single word. This would have a chance of ++ // 2⁻⁶⁴ on 64-bit platforms, and 2⁻³² on 32-bit platforms, but testing 2⁻⁶⁴ ++ // edge cases is impractical, and we'd rather not behave differently on ++ // different platforms, so we reject divisors above 2³²-1. ++ if gcd.BitLenVarTime() > 32 { ++ return nil, errDivisorTooLarge ++ } ++ if gcd.IsZero() == 1 || gcd.Bits()[0] == 0 { ++ return nil, errors.New("rsa: internal error: gcd(a, b) is zero") ++ } ++ if rem := b.DivShortVarTime(gcd.Bits()[0]); rem != 0 { ++ return nil, errors.New("rsa: internal error: b is not divisible by gcd(a, b)") ++ } ++ ++ return bigmod.NewModulusProduct(a.Bytes(p), b.Bytes(q)) ++} ++ + // randomPrime returns a random prime number of the given bit size following + // the process in FIPS 186-5, Appendix A.1.3. + func randomPrime(rand io.Reader, bits int) ([]byte, error) { +- if bits < 64 { +- return nil, errors.New("rsa: prime size must be at least 32-bit") ++ if bits < 16 { ++ return nil, errors.New("rsa: prime size must be at least 16 bits") + } + + b := make([]byte, (bits+7)/8) +diff --git a/src/crypto/internal/fips140/rsa/keygen_test.go b/src/crypto/internal/fips140/rsa/keygen_test.go +index 7d613e6ddf..9104a9dfd8 100644 +--- a/src/crypto/internal/fips140/rsa/keygen_test.go ++++ b/src/crypto/internal/fips140/rsa/keygen_test.go +@@ -6,8 +6,10 @@ package rsa + + import ( + "bufio" ++ "crypto/internal/fips140/bigmod" + "encoding/hex" + "fmt" ++ "math/big" + "os" + "strings" + "testing" +@@ -83,8 +85,94 @@ func TestMillerRabin(t *testing.T) { + } + } + ++func TestTotient(t *testing.T) { ++ f, err := os.Open("testdata/gcd_lcm_tests.txt") ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ var GCD, A, B, LCM string ++ var lineNum int ++ scanner := bufio.NewScanner(f) ++ for scanner.Scan() { ++ lineNum++ ++ line := scanner.Text() ++ if len(line) == 0 || line[0] == '#' { ++ continue ++ } ++ ++ k, v, _ := strings.Cut(line, " = ") ++ switch k { ++ case "GCD": ++ GCD = v ++ case "A": ++ A = v ++ case "B": ++ B = v ++ case "LCM": ++ LCM = v ++ ++ t.Run(fmt.Sprintf("line %d", lineNum), func(t *testing.T) { ++ if A == "0" || B == "0" { ++ t.Skip("skipping test with zero input") ++ } ++ if LCM == "1" { ++ t.Skip("skipping test with LCM=1") ++ } ++ ++ p, _ := bigmod.NewModulus(addOne(decodeHex(t, A))) ++ a, _ := bigmod.NewNat().SetBytes(decodeHex(t, A), p) ++ q, _ := bigmod.NewModulus(addOne(decodeHex(t, B))) ++ b, _ := bigmod.NewNat().SetBytes(decodeHex(t, B), q) ++ ++ gcd, err := bigmod.NewNat().GCDVarTime(a, b) ++ // GCD doesn't work if a and b are both even, but LCM handles it. ++ if err == nil { ++ if got := strings.TrimLeft(hex.EncodeToString(gcd.Bytes(p)), "0"); got != GCD { ++ t.Fatalf("unexpected GCD: got %s, want %s", got, GCD) ++ } ++ } ++ ++ lcm, err := totient(p, q) ++ if oddDivisorLargerThan32Bits(decodeHex(t, GCD)) { ++ if err != errDivisorTooLarge { ++ t.Fatalf("expected divisor too large error, got %v", err) ++ } ++ t.Skip("GCD too large") ++ } ++ if err != nil { ++ t.Fatalf("failed to calculate totient: %v", err) ++ } ++ if got := strings.TrimLeft(hex.EncodeToString(lcm.Nat().Bytes(lcm)), "0"); got != LCM { ++ t.Fatalf("unexpected LCM: got %s, want %s", got, LCM) ++ } ++ }) ++ default: ++ t.Fatalf("unknown key %q on line %d", k, lineNum) ++ } ++ } ++ if err := scanner.Err(); err != nil { ++ t.Fatal(err) ++ } ++} ++ ++func oddDivisorLargerThan32Bits(b []byte) bool { ++ x := new(big.Int).SetBytes(b) ++ x.Rsh(x, x.TrailingZeroBits()) ++ return x.BitLen() > 32 ++} ++ ++func addOne(b []byte) []byte { ++ x := new(big.Int).SetBytes(b) ++ x.Add(x, big.NewInt(1)) ++ return x.Bytes() ++} ++ + func decodeHex(t *testing.T, s string) []byte { + t.Helper() ++ if len(s)%2 != 0 { ++ s = "0" + s ++ } + b, err := hex.DecodeString(s) + if err != nil { + t.Fatalf("failed to decode hex %q: %v", s, err) +diff --git a/src/crypto/internal/fips140/rsa/rsa.go b/src/crypto/internal/fips140/rsa/rsa.go +index 7f759cff64..0bbf701050 100644 +--- a/src/crypto/internal/fips140/rsa/rsa.go ++++ b/src/crypto/internal/fips140/rsa/rsa.go +@@ -229,7 +229,7 @@ func checkPrivateKey(priv *PrivateKey) error { + // Check that de ≡ 1 mod p-1, and de ≡ 1 mod q-1. + // + // This implies that e is coprime to each p-1 as e has a multiplicative +- // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) = exponent(ℤ/nℤ). ++ // inverse. Therefore e is coprime to lcm(p-1,q-1) = λ(N). + // It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1 mod p. Thus a^de ≡ a + // mod n for all a coprime to n, as required. + // +diff --git a/src/crypto/internal/fips140/rsa/testdata/gcd_lcm_tests.txt b/src/crypto/internal/fips140/rsa/testdata/gcd_lcm_tests.txt +new file mode 100644 +index 0000000000..b5a0c17ed2 +--- /dev/null ++++ b/src/crypto/internal/fips140/rsa/testdata/gcd_lcm_tests.txt +@@ -0,0 +1,279 @@ ++# GCD tests. ++# ++# These test vectors satisfy gcd(A, B) = GCD and lcm(A, B) = LCM. ++ ++GCD = 0 ++A = 0 ++B = 0 ++# Just to appease the syntax-checker. ++LCM = 0 ++ ++GCD = 1 ++A = 92ff140ac8a659b31dd904161f9213706a08a817ae845e522c3af0c9096699e059b47c8c2f16434b1c5766ebb384b79190f2b2a62c2378f45e116890e7bb407a ++B = 2f532c9e5902b0d68cd2ed69b2083bc226e8b04c549212c425a5287bb171c6a47fcb926c70cc0d34b8d6201c617aee66af865d31fdc8a2eeb986c19da8bb0897 ++LCM = 1b2c97003e520b0bdd59d8c35a180b4aa36bce14211590435b990ad8f4c034ce3c77899581cb4ee1a022874203459b6d53859ab1d99ff755efa253fc0e5d8487bb000c13c566e8937f0fe90b95b68bc278610d4f232770b08d1f31bee55a03da47f2d0ebb9e7861c4f16cc22168b68593e9efcde00f54104b4c3e1a0b294d7f6 ++ ++GCD = a ++A = faaffa431343074f5c5d6f5788500d7bc68b86eb37edf166f699b4d75b76dae2cb7c8f6eccae8f18f6d510ef72f0b9633d5740c0bebb934d3be796bd9a53808e ++B = 2f48ec5aa5511283c2935b15725d30f62244185573203b48c7eb135b2e6db5c115c9446ac78b020574665b06a75eb287e0dbeb5da7c193294699b4c2129d2ac4 ++LCM = 4a15f305e9622aa19bd8f39e968bfc16d527a47f7a5219d7b02c242c77ef8b608a4a6141f643ca97cedf07c0f1f3e8879d2568b056718aa15c0756899a08ccbe0a658bae67face96fa110edb91757bfa4828e8ff7c5d71b204f36238b12dd26f17be8ba9771f7068d63e41d423671f898f054b1187605754bc5546f2b02c5ac ++ ++GCD = 16 ++A = cf0b21bde98b41b479ac8071086687a6707e9efaacd4e5299668ce1be8b13290f27fd32ae68df87c292e8583a09d73ec8e8a04a65a487380dcd7dacca3b6e692 ++B = 3be3f563f81d5ad5c1211db7eff430aa345e830ce07b4bde7d4d32dba3ac618d2034351e5435fd6c7f077971fb4a1e83a7396a74fdff7fce1267112851db2582 ++LCM = 233a2188de2c017235024b182286f17562b2ee5ab9fdfe4efa2f61c4ff99fa44e1ead5bf6cde05bd7502ce78373c83e3f9dbab0c9bb8620a87c2640bce5d12c685af656df789bb3d0ba1edbaa98cf4f0166d422ab17aa6706f8132264d45b72827d6671a00a9186e723379e3a3bb7902d08865f357c74100059f83800241976 ++ ++GCD = 1 ++A = dd7b7597d7c1eb399b1cea9b3042c14bd6022d31b1d2642a8f82fc32de6eadaf012fbbf349eaec4922a8468740ca73c6090833d6a69a380ed947b39c2f9b0b76 ++B = 8e0dc8654e70eec55496038a8d3fff3c2086bc6dbfc0e2dbdf5bd7de03c5aef01a3982556ac3fc34fd5f13368be6cdc252c82367b7462e210f940f847d382dd9 ++LCM = 7ae667df4bd4dd35bbec28719a9f1b5e1f396a9ab386c086742a6ab3014a3386d39f35b50624d0c5b4e6b206c2635c7de5ea69e2faa85dd616a7e36622962a07632839857aa49332942feccff2aee1c962e2f4e8ccfd738a5da5bf528b4c5a2440409350f5a17a39d234403e8482ccf838e0d2758ccfb8018198a51dbb407506 ++ ++GCD = 1 ++A = 0 ++B = 1 ++LCM = 0 ++ ++GCD = 1 ++A = 1 ++B = 0 ++LCM = 0 ++ ++GCD = 1 ++A = 1 ++B = 1 ++LCM = 1 ++ ++GCD = 2b2 ++A = dfccaa3549c1b59ab3e114fe87dc5d187719abad58c51724e972741eb895ab79a49f385f61d531ec5c88dbb505ae375093fa848165f71a5ed65e7832a42ade191a ++B = fa58a81f43088da45e659fc1117d0f1cd015aa096c8e5377cf1832191baf7cc28b5c24998b93b64f8900a0973faedb9babaaf1854345f011739da8f1175d9684c ++LCM = 5132f7ab7a982b9dc55114bd96800b7637f9742cf8a7a00a0d69d5e4574fc85792c89a1c52bcfc74b9d7f3f6164819466c46b2d622e280ced7ad1211604084a15dc1fd1951a05c8ce37122c0ec15891d818a70d3763670ea3195098de9b1ca50ea89893a9753fb9ea801541058f44801f7f50967124abfc864a2b01c41f94193c ++ ++GCD = 8e ++A = 248d96a8a4cab0a1b194e08c1146868b094597cadbc35531f0ed2d77cba9f15cb5cc7c10e64ce054bf93396d25259d750b3de3aba65073db1fd2b852a6454ac1a ++B = 4c7bad8e1844901fd6a2ce2edc82e698d28ec95d6672ca148d85b49ecc78dd0a8b870e202244210bc98592b99ff6abbd20630f9eee7d46b15ccfae8d08b86799de ++LCM = 13b01f9d9c6c13e90c97e3d95bbce5a835c631b3de3bd4ff5df13ad850f5223dbdf71c53912275d0397df9335ef3a3ba8e4684c6b25962bb7b18bc74144cb5edf0196f79863a7ff032619a71646a92281f7baace7f223d254cb4d05ec19bf8d4c8ce4455a9d770daec89c0d3cf338cbdae39cf982b3c4568f5c9def4e1133d28a ++ ++GCD = 3e55 ++A = 2fa97382f46676b7a4cc2b8153f17b58792d24660e187d33ce55c81cc193ccb6e1e2b89feea1d5fd8faa36e13bf947fb48635e450a4d1488d0978324194a1f43c6 ++B = ab08ad074139963bc18e5d87ba68db64ca6f4c279616c64039b02c55f2375b3bc04114e8e05e1ba92fb6470768f61d123845aea36774c18612736a220934561faf ++LCM = 82c7c377ecda2cb9228604cd287df5eff94edd4a539c3eb3b3fdd4b4a79d2f4eaf2b22f8286272d3dad2e370cfcd9ea4d93ebb3f049c52b8fa23b68a5bf79af989822e2cfb978f68c6a5058f47319dffcb455b089b06ae6db9e5c8a2b6e951d6e118bd2b4cd08b6e5733476a446a57387d940d1289ec00e24315821ed3a5daf2 ++ ++GCD = a7a ++A = 923706dfed67834a1e7e6c8e8e9f93bfbc0b43ca1f324886cf1f1380fb9b77109275d4b50af1b7689802fe9b3623ac46c7ba0e17e908c20278127b07a5c12d86ec ++B = 64473e878a29021fac1c1ce34a63eae1f4f83ee6851333b67213278b9a4a16f005cba0e8cdb410035bb580062f0e486c1a3a01f4a4edf782495f1dc3ebfa837d86 ++LCM = 57785ca45b8873032f1709331436995525eed815c55140582ce57fd852116835deac7ca9d95ce9f280e246ea4d4f1b7140ab7e0dd6dc869de87f1b27372098b155ad0a1828fd387dff514acc92eae708609285edaab900583a786caf95153f71e6e6092c8c5ee727346567e6f58d60a5e01c2fa8ebcf86da9ea46876ecc58e914 ++ ++GCD = 42 ++A = 0 ++B = 42 ++LCM = 0 ++ ++GCD = 42 ++A = 42 ++B = 0 ++LCM = 0 ++ ++GCD = 42 ++A = 42 ++B = 42 ++LCM = 42 ++ ++GCD = f60d ++A = ef7886c3391407529d5cf2e75ed53e5c3f74439ad2e2dc48a79bc1a5322789b4ced2914b97f8ff4b9910d212243b54001eb8b375365b9a87bd022dd3772c78a9fd63 ++B = d1d3ec32fa3103911830d4ec9f629c5f75af7039e307e05bc2977d01446cd2cbeeb8a8435b2170cf4d9197d83948c7b8999d901fe47d3ce7e4d30dc1b2de8af0c6e4 ++LCM = cc376ed2dc362c38a45a719b2ed48201dab3e5506e3f1314e57af229dc7f3a6a0dad3d21cfb148c23a0bbb0092d667051aa0b35cff5b5cc61a7c52dec4ed72f6783edf181b3bf0500b79f87bb95abc66e4055f259791e4e5eb897d82de0e128ecf8a091119475351d65b7f320272db190898a02d33f45f03e27c36cb1c45208037dc ++ ++GCD = 9370 ++A = 1ee02fb1c02100d1937f9749f628c65384ff822e638fdb0f42e27b10ee36e380564d6e861fcad0518f4da0f8636c1b9f5124c0bc2beb3ca891004a14cd7b118ddfe0 ++B = 67432fd1482d19c4a1c2a4997eab5dbf9c5421977d1de60b739af94c41a5ad384cd339ebfaa43e5ad6441d5b9aaed5a9f7485025f4b4d5014e1e406d5bd838a44e50 ++LCM = 159ff177bdb0ffbd09e2aa7d86de266c5de910c12a48cbe61f6fa446f63a2151194777555cd59903d24cb30965973571fb1f89c26f2b760526f73ded7ee8a34ebcecd1a3374a7559bcdb9ac6e78be17a62b830d6bb3982afdf10cf83d61fd0d588eab17d6abef8e6a7a5763fcb766d9a4d86adf5bb904f2dd6b528b9faec603987a0 ++ ++GCD = c5f ++A = 5a3a2088b5c759420ed0fb9c4c7685da3725b659c132a710ef01e79435e63d009d2931ea0a9ed9432f3d6b8851730c323efb9db686486614332c6e6ba54d597cf98 ++B = 1b1eb33b006a98178bb35bbcf09c5bebd92d9ace79fa34c1567efa8d6cf6361547807cd3f8e7b8cd3ddb6209dccbae4b4c16c8c1ec19741a3a57f61571882b7aed7 ++LCM = c5cbbbe9532d30d2a7dd7c1c8a6e69fd4fa4828a844d6afb44f3747fef584f7f1f3b835b006f8747d84f7699e88f6267b634e7aef78d6c7584829537d79514eec7d11219721f91015f5cefdc296261d85dba388729438991a8027de4827cd9eb575622e2912b28c9ce26d441e97880d18db025812cef5de01adeaec1322a9c9858 ++ ++GCD = e052 ++A = 67429f79b2ec3847cfc7e662880ab1d94acdf04284260fcfffd67c2862d59704ed45bcc53700c88a5eea023bc09029e9fd114fc94c227fd47a1faa1a5ef117b09bd2 ++B = 39faa7cbdeb78f9028c1d50ab34fbe6924c83a1262596f6b85865d4e19cc258b3c3af1ee2898e39e5bee5839e92eac6753bbbb0253bd576d1839a59748b778846a86 ++LCM = 1ab071fb733ef142e94def10b26d69982128561669e58b20b80d39cf7c2759d26b4a65d73b7f940c6e8fc417180ef62d7e52ac24678137bd927cd8d004ad52b02affe176a1ecde903dbc26dcc705678f76dd8cd874c0c3fe737474309767507bbe70dd7fb671bbb3694cedf0dcdaa0c716250ddd6dfec525261572fa3e1387f7b906 ++ ++GCD = 3523 ++A = 0 ++B = 3523 ++LCM = 0 ++ ++GCD = 3523 ++A = 3523 ++B = 0 ++LCM = 0 ++ ++GCD = 3523 ++A = 3523 ++B = 3523 ++LCM = 3523 ++ ++GCD = f035a941 ++A = 16cd5745464dfc426726359312398f3c4486ed8aaeea6386a67598b10f744f336c89cdafcb18e643d55c3a62f4ab2c658a0d19ea3967ea1af3aee22e11f12c6df6e886f7 ++B = 74df09f309541d26b4b39e0c01152b8ad05ad2dfe9dd2b6706240e9d9f0c530bfb9e4b1cad3d4a94342aab309e66dd42d9df01b47a45173b507e41826f24eb1e8bcc4459 ++LCM = b181771d0e9d6b36fdfcbf01d349c7de6b7e305e1485ea2aa32938aa919a3eee9811e1c3c649068a7572f5d251b424308da31400d81ac4078463f9f71d7efd2e681f92b13a6ab3ca5c9063032dcbdf3d3a9940ce65e54786463bbc06544e1280f25bc7579d264f6f1590cf09d1badbf542ce435a14ab04d25d88ddbac7d22e8cae1c91f ++ ++GCD = 33ad1b8f ++A = 1af010429a74e1b612c2fc4d7127436f2a5dafda99015ad15385783bd3af8d81798a57d85038bcf09a2a9e99df713b4d6fc1e3926910fbbf1f006133cb27dc5ebb9cca85 ++B = 92a4f45a90965a4ef454f1cdd883d20f0f3be34d43588b5914677c39d577a052d1b25a522be1a656860a540970f99cbc8a3adf3e2139770f664b4b7b9379e13daf7d26c ++LCM = 4c715520ed920718c3b2f62821bc75e3ff9fd184f76c60faf2906ef68d28cd540d3d6c071fa8704edd519709c3b09dfaee12cb02ab01ad0f3af4f5923d5705ce6d18bcab705a97e21896bb5dd8acb36ee8ec98c254a4ddc744297827a33c241f09016a5f109248c83dd41e4cea73ce3eabb28d76678b7e15545b96d22da83c111b6b624 ++ ++GCD = dc0429aa ++A = ccb423cfb78d7150201a97114b6644e8e0bbbb33cadb0ef5da5d3c521a244ec96e6d1538c64c10c85b2089bdd702d74c505adce9235aa4195068c9077217c0d431de7f96 ++B = 710786f3d9022fc3acbf47ac901f62debcfda684a39234644bac630ab2d211111df71c0844b02c969fc5b4c5a15b785c96efd1e403514235dc9356f7faf75a0888de5e5a ++LCM = 6929af911850c55450e2f2c4c9a72adf284fe271cf26e41c66e1a2ee19e30d928ae824f13d4e2a6d7bb12d10411573e04011725d3b6089c28d87738749107d990162b485805f5eedc8f788345bcbb5963641f73c303b2d92f80529902d3c2d7899623958499c8a9133aae49a616c96a2c5482a37947f23af18c3247203ac2d0e760340e6 ++ ++GCD = 743166058 ++A = 16cd476e8031d4624716238a3f85badd97f274cdfd9d53e0bd74de2a6c46d1827cc83057f3889588b6b7ca0640e7d743ed4a6eaf6f9b8df130011ecc72f56ef0af79680 ++B = 86eba1fc8d761f22e0f596a03fcb6fe53ad15a03f5b4e37999f60b20966f78ba3280f02d3853f9ace40438ccfaf8faed7ace2f2bf089b2cdd4713f3f293bf602666c39f8 ++LCM = 1a7a1b38727324d6ba0290f259b8e2b89c339b2445cada38a5a00ded1468ab069f40678ce76f7f78c7c6f97783cc8a49ef7e2a0c73abbac3abc66d1ce99566ce7f874a8949ca3442051e71967695dc65361184748c1908e1b587dc02ed899a524b34eb30b6f8db302432cfa1a8fbf2c46591e0ab3db7fd32c01b1f86c39832ee9f0c80 ++ ++GCD = 6612ba2c ++A = 0 ++B = 6612ba2c ++LCM = 0 ++ ++GCD = 6612ba2c ++A = 6612ba2c ++B = 0 ++LCM = 0 ++ ++GCD = 6612ba2c ++A = 6612ba2c ++B = 6612ba2c ++LCM = 6612ba2c ++ ++GCD = 2272525aa08ccb20 ++A = 11b9e23001e7446f6483fc9977140d91c3d82568dabb1f043a5620544fc3dda233b51009274cdb004fdff3f5c4267d34181d543d913553b6bdb11ce2a9392365fec8f9a3797e1200 ++B = 11295529342bfb795f0611d03afb873c70bd16322b2cf9483f357f723b5b19f796a6206cf3ae3982daaeafcd9a68f0ce3355a7eba3fe4e743683709a2dd4b2ff46158bd99ff4d5a0 ++LCM = 8d4cbf00d02f6adbaa70484bcd42ea932000843dcb667c69b75142426255f79b6c3b6bf22572597100c06c3277e40bf60c14c1f4a6822d86167812038cf1eefec2b0b19981ad99ad3125ff4a455a4a8344cbc609e1b3a173533db432bd717c72be25e05ed488d3970e7ed17a46353c5e0d91c8428d2fec7a93210759589df042cab028f545e3a00 ++ ++GCD = 3480bf145713d56f9 ++A = 8cf8ef1d4f216c6bcec673208fd93b7561b0eb8303af57113edc5c6ff4e1eeae9ddc3112b943d947653ba2179b7f63505465126d88ad0a0a15b682f5c89aa4a2a51c768cd9fdeaa9 ++B = a6fd114023e7d79017c552a9051ca827f3ffa9f31e2ee9d78f8408967064fcdc9466e95cc8fac9a4fa88248987caf7cf57af58400d27abd60d9b79d2fe03fad76b879eceb504d7f ++LCM = 1c05eee73a4f0db210a9007f94a5af88c1cdd2cba456061fd41de1e746d836fa4e0e972812842e0f44f10a61505f5d55760c48ba0d06af78bb6bde7da8b0080b29f82b1161e9c0b5458e05ac090b00f4d78b1cc10cf065124ba610e3acab092a36fe408525e21c0ddc7c9696ed4e48bd2f70423deecfe62cecc865c6088f265da0e5961d3f3a84f ++ ++GCD = 917e74ae941fcaae ++A = 652f8a92d96cbf0a309629011d0fbaceb1266bc2e8243d9e494eead4cf7100c661b537a8bea93dec88cfc68597d88a976c125c3b4de19aba38d4ea9578202e59848d42652518348a ++B = 32e07b71979d57e8344e97c39680a61e07d692d824ae26b682156890792d8a766ee29a4968f461aaced5bf049044fba2f4120b1c1f05985676f975d4582e9e82750d73c532cd07b2 ++LCM = 23620c7b897dc26c7717e32f3517ac70bf09fbe08f7255ab010cf4cf946f4e96304c425043452c5d5a0e841d3a3cfd9c2d84d9256f3b5974fe3ebfa9255fe20a710d3e6511606c0d85970381101c7f4986d65ad6a73a71507f146b11f903043cfa805cc0b14d4f3072da98bf22282f7762040406c02d5b3ef9e7587f63bab8b29c61d8e30911aa96 ++ ++GCD = 2b9adc82005b2697 ++A = 19764a84f46045ef1bca571d3cbf49b4545998e64d2e564cc343a53bc7a0bcfbe0baa5383f2b346e224eb9ce1137d9a4f79e8e19f946a493ff08c9b423574d56cbe053155177c37 ++B = 1bbd489ad2ab825885cdac571a95ab4924e7446ce06c0f77cf29666a1e20ed5d9bc65e4102e11131d824acad1592075e13024e11f12f8210d86ab52aa60deb250b3930aabd960e5a ++LCM = 1032a0c5fffc0425e6478185db0e5985c645dd929c7ebfeb5c1ee12ee3d7b842cfab8c9aa7ff3131ac41d4988fb928c0073103cea6bb2cc39808f1b0ad79a6d080eac5a0fc6e3853d43f903729549e03dba0a4405500e0096b9c8e00510c1852982baec441ed94efb80a78ed28ed526d055ad34751b831b8749b7c19728bf229357cc5e17eb8e1a ++ ++GCD = 8d9d4f30773c4edf ++A = 0 ++B = 8d9d4f30773c4edf ++LCM = 0 ++ ++GCD = 8d9d4f30773c4edf ++A = 8d9d4f30773c4edf ++B = 0 ++LCM = 0 ++ ++GCD = 8d9d4f30773c4edf ++A = 8d9d4f30773c4edf ++B = 8d9d4f30773c4edf ++LCM = 8d9d4f30773c4edf ++ ++GCD = 6ebd8eafb9a957a6c3d3d5016be604f9624b0debf04d19cdabccf3612bbd59e00 ++A = 34dc66a0ffd5b8b5e0ffc858dfc4655753e59247c4f82a4d2543b1f7bb7be0e24d2bbf27bb0b2b7e56ee22b29bbde7baf0d7bfb96331e27ba029de9ffdff7bdb7dc4da836d0e58a0829367ec84ea256833fd4fe1456ad4dd920557a345e12000 ++B = 1f3406a20e20ebf96ccb765f898889a19b7636608fd7dc7c212607b641399543f71111d60e42989de01eaa6ff19a86ea8fbde1a3d368c0d86dc899e8e250fc764090f337958ca493119cbb4ad70cbfae7097d06d4f90ec62fbdd3f0a4496e600 ++LCM = ee502c50e3667946e9089d0a9a0382e7fd0b75a17db23b56a0eec997a112c4dbd56d188808f76fe90451e5605550c9559ef14a95014c6eb97e9c1c659b98515c41470142843de60f72fb4c235faa55b0a97d943221003d44e2c28928f0b84bf071256254897ed31a7fd8d174fc962bc1311f67900ac3abcad83a28e259812f1ee229511ab1d82d41f5add34693ba7519babd52eb4ec9de31581f5f2e40a000 ++ ++GCD = ef7399b217fc6a62b90461e58a44b22e5280d480b148ec4e3b4d106583f8e428 ++A = 7025e2fe5f00aec73d90f5ad80d99ca873f71997d58e59937423a5e6ddeb5e1925ed2fd2c36a5a9fc560c9023d6332c5d8a4b333d3315ed419d60b2f98ccf28bbf5bf539284fd070d2690aeaac747a3d6384ee6450903a64c3017de33c969c98 ++B = df0ac41dbabce1deeb0bceb1b65b1079850052ecf6534d0cff84a5a7fb5e63baee028d240f4419925154b96eaa69e8fbb1aae5102db7916234f290aa60c5d7e69406f02aeea9fe9384afbff7d878c9ac87cd31f7c35dff243b1441e09baff478 ++LCM = 687669343f5208a6b2bb2e2efcac41ec467a438fde288cc5ef7157d130139ba65db9eb53e86a30c870bd769c0e0ab15a50f656cd9626621ae68d85eaff491b98da3ea5812062e4145af11ea5e1da457084911961ef2cd2ac45715f885ba94b4082aa76ffd1f32461f47c845b229d350bf36514c5ce3a7c782418746be342eca2721346ade73a59475f178c4f2448e1326110f5d26a0fef1a7a0c9288489e4dc8 ++ ++GCD = 84b917557acf24dff70cb282a07fc52548b6fbbe96ca8c46d0397c8e44d30573 ++A = 81dbb771713342b33912b03f08649fb2506874b96125a1ac712bc94bfd09b679db7327a824f0a5837046f58af3a8365c89e06ff4d48784f60086a99816e0065a5f6f0f49066b0ff4c972a6b837b63373ca4bb04dcc21e5effb6dfe38271cb0fa ++B = 1da91553c0a2217442f1c502a437bb14d8c385aa595db47b23a97b53927b4493dd19f1bc8baf145bc10052394243089a7b88d19b6f106e64a5ab34acad94538ab504d1c8ebf22ac42048bbd1d4b0294a2e12c09fe2a3bd92756ba7578cb34b39 ++LCM = 1d0530f8142754d1ee0249b0c3968d0ae7570e37dadbe4824ab966d655abf04cd6de5eb700eba89d8352dec3ae51f2a10267c32fbd39b788c7c5047fe69da3d7ad505435a6212f44899ba7e983bb780f62bcdee6f94b7dba8af7070a4cc008f351ae8be4579bc4a2e5c659ce000ad9c8cdc83723b32c96aeb0f5f4127f6347353d05525f559a8543cd389ad0af6f9d08a75b8c0b32419c097e6efe8746aee92e ++ ++GCD = 66091477ea3b37f115038095814605896e845b20259a772f09405a8818f644aa ++A = cedac27069a68edfd49bd5a859173c8e318ba8be65673d9d2ba13c717568754ed9cbc10bb6c32da3b7238cff8c1352d6325668fd21b4e82620c2e75ee0c4b1aff6fb1e9b948bbdb1af83cecdf356299b50543b72f801b6a58444b176e4369e0 ++B = 5f64ca1ba481f42c4c9cf1ffa0e515b52aa9d69ceb97c4a2897f2e9fa87f72bae56ee6c5227f354304994c6a5cc742d9f09b2c058521975f69ca5835bce898cf22b28457cd7e28870df14e663bb46c9be8f6662f4ff34d5c4ae17a888eba504e ++LCM = c163cb28642e19a40aa77887c63180c2c49fc10cda98f6f929c8131752ea30b5283a814a81681b69b9d1762e6c1a9db85f480bc17f998d235fd7e64c1caa70ef170c9e816d3e80f516b29f2c80cfb68bf208b4d5082ef078da4314b3f20c7d6c54b0aeb378096b029a7b61c0a4cd14aeddc01004c53915a4f692d2291752e5af46b23d7fa6dd61f2d56c6f4bf8e6119688abac8fd7aba80e846a7764bb3fca0 ++ ++GCD = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 ++A = 0 ++B = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 ++LCM = 0 ++ ++GCD = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 ++A = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 ++B = 0 ++LCM = 0 ++ ++GCD = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 ++A = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 ++B = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 ++LCM = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 ++ ++GCD = 120451d8307219aa0c96f328ad653ccd462e92423ca93ed8a3dde45bf5cb9b13cdaf9800e4d05dd71c4db6a129fb3280ee4ec96ec5297d881c1a8b5efccbd91fef21f5c5bf5fba42a4c8eaa358f620a074b7a17054527bdaa58d5acaa0dfdc48ecba1a10ebf4d57bb4215de406e6be13fed3fe493b1cd1e2d11a8d4ac03c47756 ++A = 3f8179a8e1f0b342475a855c3e1bae402dd41424cf24a0b4d2e263c8efb08bde7d92eae8607fb5e88b1378f0f1bd0733f229a35be6b1383a48d32749d5d6b32427d26323b7ab05bb5781289e96bfbc21971439319b15f6c0fe93fdb35d0b67ec41443c59a081dd3cef047ac797fccb45bece84c0bb0bb7e1797259526d8ec9cc63ba4d32cfc692ccd3d243cb2b53ac216312f3a8e8c0daa09d21b6150d697639a5e52059414a417c607be8ec0eee2e708219cadbaf37a369c4485b01ed87bbc2 ++B = 2c474e396a2dd9cd10b9d7313f69d3b4ca123e9fd853edd488339236d14c56453a1381958864a04d2624e81995dabcdd0ccf60db9917813f887de68da075d0ea4440001e18f470e43b38ee3440b49be651d709fbdef980e3e4149913f4ae2681124f54523f4881376ddb533b5219e804cc26f4c2e577be4e02613c4da80ba1215775b0a5178a965ad47bd2befb32493943ded1004ef66347b4983f8d1ba990d4a943505dfce6debcfb322842ed88106cd6dee9aa592ff0d2274bc727a6e1f14c ++LCM = 9c129cf649555bfd2d3d9c64dc6d6f022295e53bca5d2f218adaa66aa60eb4694429b7e83bf81b6df4459c5104023ab9a33f006ffcd8114507baa17e2ef6fe23ebdd4740f66879033da2041f2cb7ba517ad3526ffe75614ea9432c085f71b2d65a736bac7ba42b639e330b82733372083843dcb78b6a273ab20e0d4b7c8998a14048aa15bb20a0a0bd997917107274c89b4cec175fb98043d52e6c555bd9e0036566d052a6d4e7e276d1e8835e1f06e3ca46d47747ba586e95fb1a790d992834b7c3e136141eb8a434e6c12067246ac3c0a81c69e03b1ed28aa0b3173d6eff83d278c2f461a47a416f3f9a5dae3bb410fd18817bd4115e7f1e84b936cc02364 ++ ++GCD = 95aa569a2c76854300d7660847dd20fe0b8c445fdbcaa98465cee61aee76ad6a438e75a8c573198570ffb62bc07ec3a2be0ae0a1f631670fa88d6f75f3161e8b9a4d44b6801ffc884c7f469c5ed1f27b1edecce9f2977f9e92d1a3b230492fea7e6f2af739dc158a7fbd29856cbedb57b4119e64b27ab09eb1c2df01507d6e7fd ++A = 4c653b5bfec44e9be100c064dffe5d8cd59b0cf4cc56b03eabb4ef87cfda6506c9a756b811907fe9d8b783eb7a0b9e129773bf1da365ddb488d27b16fb983e89345d1ccdb4f06a67a11925c3f266373be5d7b0075189c6f3c2157e2da197058fe0a7bcc50adc34e99e254a29abbe2d5948d3157e1b0c3fca3d641760f7b9862843b63abef0b3d83fd486f4526b30382fda355575da30e9a106718a3921774c4d69f5311f8d737fe618f5236b4763fe1b2ee7f13184db67367d3903c535ff6d7b ++B = 2dcca83c99a28e9fd2f84e78973699baf2f04fd454094730948b22477834a0064817b86e0835e6d7b26e5b0b1dcf4ad91a07ac0780d6522df1fcac758cf5db6c2a5623d7c0f1afefd5718f7b6de639867d07a9ec525991304e9355d1635104bea837f74758d6aa2aab4e4afbb606af1d98de7417505e4710cd0589bdff9a0bf38a857cc59a5f1781043e694fc2337fd84bdeb28b13a222bb09328a81ec409ad586e74236393d27398cc24d412135e34247c589149e134b97f4bd538ac9a3424b ++LCM = 1760c0b0066aa0695767099e87e9388729ea89b8e8c36bddcd04d257591e741613c07b0e69447c0a468c33a745084171e06523d987d8db40a1433bf435325e8a724a0876503b34495170ff3671d42117a2e4f3a75b1d9dd809a34fa0fb26fe50d84f80a9b02e40190e5efb927a5a61a03f13edbce2e666af6c3a2a9bcb84e47e3090008753ff27c4b8cf06480f471379a93f5230923623a83b286b71a555cd5e5347282f664ed90b14b2c4de84a70375e488211a7b3931119ef3bbe029b712389fe784818a0bf29d80733ce9cc940c547aa1eb3f06d492eb676bf37802283c82ce76156dfaab5c2d5107e08062681b5fa169f6eb68e1ab8bd9b2005e90bd4fd ++ ++GCD = 244b9b1290cf5b4ba2f810574c050651489f2d3a2b03e702b76ebfaf4e33de9bbe5da24c919e68d3a72eadd35982b3a89c6b18b38ff7082ac65263e52b6ec75a5717b971c98257b194c828bff0216a99536603b41a396ea2fb50f5ea7cf3edf10bb0d039123e78593ae9ffcbbba02e51e038533e83b6bc73c70551d6467f39809 ++A = 41a0b1310669500681cdf888836f6c556758750f562d743ac780dd4c0d161856380e44fdbb1f8a2786bf45be6b0e7f1cb2cd85f6b9e50acc72793d92383c7d7fb796fc74d32e8fac8225bdc19ae47546d9c9c75f5f06ca684f07daccaf89ccf2cddeb7ec255d530c7dd1e71daf44cafdc9d30fbcb1cbaefae3480585f79f4177e3834a5bc91845e2e8cd8aeb27f484e5e5b2c3c076dbb6c23e91303f0a0fdde83cd33a8ea6ed1549e727b4d766c1017c169710fd98e1585d60f66e121f9180b3 ++B = 251f5aeaa60b3959285f49540cdaf8e21451110bbddb9933bbbcaea3112f4eb45e435a3ba37c52d2ab79ce997a8f6c829b3aa561f2852924b8effb52396d09d2bf257ebb4fb56c7aa25648f69b06d2cd01e876c9f9c0679de9e6fffa79eb7e603723e5af7de46ee405a5a079229577b5b6fffb8d43e391fe6f4eb89638e64d6eff8026249aaa355a91625eb0bfd14caa81e4c3586aaa2e94fde143a44f223a91e226661d12f55dfcdb4215e5a64e14e968005733be6a71c465de312ca109b34a ++LCM = 431f918b274f3e43f446e4e85567883d6536a0332db662cef088f5a36b0f4b68372048174ba10fee94b9f8f1c2e189c974be2e6e8ae8e2ae108445326d40f63e38d8d4e2e46174589a3cbc9583e0036dc8146e79eee9e96f4436313b3f143dd0f5aceab05243def7f915169c360f55ef123977cf623c5ba432c3259c62fb5e37d5adab0f24b825aa4ada99ec4e83e9ca4698399e1ed633091ce5f9844c540a642cd264201116ed4168aa2105a5159f5df064f845830c469140f766c7319052ce59bd1ad7c3f2d8c30e54f147f6aeb5586c70c984302ba18d854a60aec01b394c7d66fa33fe18fe4a8cfb3238df219294e6e42190a30d28b10049a1b75853a4e ++ ++GCD = 206695d52bc391a4db61bf8cb6ea96188333a9c78f477ee76976c2346dad682cf56ca6f176d86ef67d41ff5921b6162b0eca52359975872430dd14c45643eacdf028d830770714c033fd150669705851b2f02de932322d271d565d26768530c3f6cb84f0b3356f970b9070b26c050ead0417152c324c8ffe266d4e8b5b7bef3a ++A = 1114eb9f1a9d5947eb1399e57f5c980833489685023ed2fe537fe1276c1e026b9a19e6fff55aa889d6c4e977b6e6f3111e2ad463138637b50f42cf32e57d83f282de9e72f813e5969195159a666d74dcd689bd527c60199ae327f7bd548ac36868fea5fdf6f35d19b921e7c10b6448ca480de6826478cd0642d72f05af3f8e65ce42409fbd49f56e81946e89c8e83962c4edc0ed54600600a305e52d081aed3c351e450e11f8fb0ce5754c92cf765b71393b2b7a89c95df79b9ea1b3cb600862 ++B = 1d8f3179ca7b5cc7119360c10de939ffa57c9043da2f2b0ca3009c9bdad9f19ed16e3c2c197bef4b527fa1bf2bbab98b77e26c329911db68bd63d3d0fbfc727a977395b9ad067106de3094d68e097830858c5ccfa505fc25e972bdee6f347e7d1163efacd3d29a791ec2a94ffeed467884ae04896efc5e7e5f43d8d76c147e3c9951a1999173bc4e5767d51268b92cc68487ba1295372143b538711e0a62bf0ac111cc750ca4dd6c318c9cbe106d7fc492261404b86a1ba728e2d25b1976dc42 ++LCM = f9570211f694141bfb096560551080cbe02a80271b4505591aaea9e3b99ea1d5ac1c1f2378fd72799e117ac2a73381b1ad26314e39972164d93971479ee3ba21a4d98cef0bd299d540ce5826995dcee0de420dff73d30b23cbf3188c625c7696df517535bc5675d71faa00807efbebdca547933f4a37849d1c014484a77da6df0670c4974bcc91eb5f5fe5faf9dd095ef195ec32ad9eeebf0e63288b4032ed9e70b888afc642f4ff96f0b4c0a68787301c12e4527fe79bdfe72dd3844ab5e094a9295df6616f24d1b9eeebc2116177dacf91969dda73667bc421ef3ccd8d5c23dddc283f5d36568d31f2654926be67f78e181075bdc148f2b39c630b141ae8a ++ ++GCD = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 ++A = 0 ++B = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 ++LCM = 0 ++ ++GCD = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 ++A = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 ++B = 0 ++LCM = 0 ++ ++GCD = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 ++A = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 ++B = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 ++LCM = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 ++ ++GCD = 2 ++A = 14e95a85e59ade9ef39e2f400c65db18702fa5fc485b9bba479a5282b2206129160e54f73ef4917983c17b4c5ebff7be112a886de069706eee29ba902515cb038 ++B = ddcfff1d39c90c599f55495bf71c1e7597c6b08b7430707f360c6a6e5137bbc7b403c6d9e2c34f3d2f29d5d32b869346853c2de239cc35381bdfb4a01569211a ++LCM = 90f38564ee72e55d362c04599e7d74f068c75f541b84e97abba2841f1a9f66b06b5c9009f6a4c2e319fced85270588de03ccebddbd9279aaecb13bdc1dbea7f42acaee751cb7da83779b8785cc86f41b94b13b54964208ca287d981634778d1096f20e76ca636c0717fd27e0800c43f599a5eded807421b502eaf9990a8c8ed8 ++ ++GCD = 4 ++A = 3c719c1c363cdeb7b57c2aabb71f425da4c3e6d3e447204d555e7cf0f3d372bdda906f36078045044978dafc20171767c8b1464d52dfdf3e2ba8a4906da033a8 ++B = 30fe0ef151ac51404e128c064d836b191921769dc02d9b09889ed40eb68d15bfdd2edea33580a1a4d7dcee918fefd5c776cbe80ca6131aa080d3989b5e77e1b24 ++LCM = 2e4526157bbd765b0486d90bcd4728f890bc6dbd9a855c67ca5cb2d6b48f8e74e1d99485999e04b193afca58dbf282610185d6c0272007744ff26e00dbdc813929b47940b137dc56ba974da07d54a1c50ec4a5c2b26e83f47cf17f4ccce8c3687e8d1e91d7c491a599f3d057c73473723ce9eee52c20fe8ae1595447552a7ee8 ++ ++GCD = 10 ++A = 44e04071d09119ea9783a53df35de4a989200133bb20280fdca6003d3ca63fdd9350ad1a1673d444d2f7c7be639824681643ec4f77535c626bd3ee8fa100e0bb0 ++B = ca927a5a3124ce89accd6ac41a8441d352a5d42feb7f62687a5ebc0e181cc2679888ecc2d38516bdc3b3443550efccac81e53044ae9341ecace2598fe5ce67780 ++LCM = 36805ba9b2412a0cb3fe4ed9bdabfa55515c9d615a3d0af268c45c5f6098d2de4a583f3791f1e3883c55d51ce23c5658fd0e8faa9a3709a1cfbd6a61dbab861690f27c86664f084c86cfd4a183b24aaadf59a6f8cbec04f1b0ded8a59b188cb46ae920052e3e099a570540dbc00f7d4a571eef08aa70d2d189a1804bf04e94a80 ++ ++GCD = 100 ++A = 73725032b214a677687c811031555b0c51c1703f10d59b97a4d732b7feaec5726cb3882193419d3f057583b2bc02b297d76bb689977936febaae92638fdfc46a00 ++B = 979f4c10f4dc60ad15068cedd62ff0ab293aeaa1d6935763aed41fe3e445de2e366e8661eadf345201529310f4b805c5800b99f351fddab95d7f313e3bb429d900 ++LCM = 4460439b4be72f533e9c7232f7e99c48328b457969364c951868ceab56cb2cbbeda8be2e8e3cae45c0758048468b841fdb246b2086d19b59d17b389333166ab82ed785860620d53c44f7aaaff4625ee70fb8072df10fb4d1acb142eadc02978ff2bb07cea9f434e35424b3323a7bda3a1a57aa60c75e49ebb2f59fb653aa77da00 ++ ++GCD = 100000000 ++A = f8b4f19e09f5862d79fb2931c4d616a1b8e0dd44781ca52902c8035166c8fca52d33a56ff484c365ec1257de7fa8ed2786163cfc051d5223b4aad859a049e8ba00000000 ++B = 6e54cb41b454b080e68a2c3dd0fa79f516eb80239af2be8250ca9cd377ba501aabafc09146fad4402bdc7a49f2c3eec815e25f4c0a223f58e36709eefd92410500000000 ++LCM = 6b3020a880ddeff9d17d3dc234da8771962de3322cd15ba7b1e4b1dd4a6a2a802a16c49653865c6fdf6c207cbe0940f8d81ef4cb0e159385fd709d515ee99d109ad9ad680031cbae4eab2ed62944babdade4e3036426b18920022f737897c7d751dce98d626cdda761fec48ad87a377fb70f97a0a15aa3d10d865785719cc5a200000000 +diff --git a/src/crypto/internal/fips140test/check_test.go b/src/crypto/internal/fips140test/check_test.go +index b156de2cbb..6b0cd3f39e 100644 +--- a/src/crypto/internal/fips140test/check_test.go ++++ b/src/crypto/internal/fips140test/check_test.go +@@ -5,15 +5,14 @@ + package fipstest + + import ( ++ "crypto/internal/fips140" + . "crypto/internal/fips140/check" + "crypto/internal/fips140/check/checktest" + "fmt" + "internal/abi" +- "internal/asan" + "internal/godebug" + "internal/testenv" + "os" +- "runtime" + "testing" + "unicode" + "unsafe" +@@ -35,12 +34,8 @@ func TestFIPSCheckVerify(t *testing.T) { + return + } + +- if !Supported() { +- t.Skipf("skipping on %s-%s", runtime.GOOS, runtime.GOARCH) +- } +- if asan.Enabled { +- // Verification panics with asan; don't bother. +- t.Skipf("skipping with -asan") ++ if err := fips140.Supported(); err != nil { ++ t.Skipf("skipping: %v", err) + } + + cmd := testenv.Command(t, os.Args[0], "-test.v", "-test.run=TestFIPSCheck") +@@ -57,8 +52,8 @@ func TestFIPSCheckInfo(t *testing.T) { + return + } + +- if !Supported() { +- t.Skipf("skipping on %s-%s", runtime.GOOS, runtime.GOARCH) ++ if err := fips140.Supported(); err != nil { ++ t.Skipf("skipping: %v", err) + } + + // Check that the checktest symbols are initialized properly. +diff --git a/src/crypto/mlkem/mlkem1024.go b/src/crypto/mlkem/mlkem1024.go +index 530aacf00f..05bad1eb2a 100644 +--- a/src/crypto/mlkem/mlkem1024.go ++++ b/src/crypto/mlkem/mlkem1024.go +@@ -91,6 +91,6 @@ func (ek *EncapsulationKey1024) Bytes() []byte { + // encapsulation key, drawing random bytes from crypto/rand. + // + // The shared key must be kept secret. +-func (ek *EncapsulationKey1024) Encapsulate() (ciphertext, sharedKey []byte) { ++func (ek *EncapsulationKey1024) Encapsulate() (sharedKey, ciphertext []byte) { + return ek.key.Encapsulate() + } +diff --git a/src/crypto/mlkem/mlkem768.go b/src/crypto/mlkem/mlkem768.go +index d6f5c94171..c367c551e6 100644 +--- a/src/crypto/mlkem/mlkem768.go ++++ b/src/crypto/mlkem/mlkem768.go +@@ -101,6 +101,6 @@ func (ek *EncapsulationKey768) Bytes() []byte { + // encapsulation key, drawing random bytes from crypto/rand. + // + // The shared key must be kept secret. +-func (ek *EncapsulationKey768) Encapsulate() (ciphertext, sharedKey []byte) { ++func (ek *EncapsulationKey768) Encapsulate() (sharedKey, ciphertext []byte) { + return ek.key.Encapsulate() + } +diff --git a/src/crypto/mlkem/mlkem_test.go b/src/crypto/mlkem/mlkem_test.go +index ddc52dab97..207d6d48c3 100644 +--- a/src/crypto/mlkem/mlkem_test.go ++++ b/src/crypto/mlkem/mlkem_test.go +@@ -43,7 +43,7 @@ func testRoundTrip[E encapsulationKey, D decapsulationKey[E]]( + t.Fatal(err) + } + ek := dk.EncapsulationKey() +- c, Ke := ek.Encapsulate() ++ Ke, c := ek.Encapsulate() + Kd, err := dk.Decapsulate(c) + if err != nil { + t.Fatal(err) +@@ -66,7 +66,7 @@ func testRoundTrip[E encapsulationKey, D decapsulationKey[E]]( + if !bytes.Equal(dk.Bytes(), dk1.Bytes()) { + t.Fail() + } +- c1, Ke1 := ek1.Encapsulate() ++ Ke1, c1 := ek1.Encapsulate() + Kd1, err := dk1.Decapsulate(c1) + if err != nil { + t.Fatal(err) +@@ -86,7 +86,7 @@ func testRoundTrip[E encapsulationKey, D decapsulationKey[E]]( + t.Fail() + } + +- c2, Ke2 := dk.EncapsulationKey().Encapsulate() ++ Ke2, c2 := dk.EncapsulationKey().Encapsulate() + if bytes.Equal(c, c2) { + t.Fail() + } +@@ -115,7 +115,7 @@ func testBadLengths[E encapsulationKey, D decapsulationKey[E]]( + } + ek := dk.EncapsulationKey() + ekBytes := dk.EncapsulationKey().Bytes() +- c, _ := ek.Encapsulate() ++ _, c := ek.Encapsulate() + + for i := 0; i < len(dkBytes)-1; i++ { + if _, err := newDecapsulationKey(dkBytes[:i]); err == nil { +@@ -189,7 +189,7 @@ func TestAccumulated(t *testing.T) { + o.Write(ek.Bytes()) + + s.Read(msg[:]) +- ct, k := ek.key.EncapsulateInternal(&msg) ++ k, ct := ek.key.EncapsulateInternal(&msg) + o.Write(ct) + o.Write(k) + +@@ -244,7 +244,7 @@ func BenchmarkEncaps(b *testing.B) { + if err != nil { + b.Fatal(err) + } +- c, K := ek.key.EncapsulateInternal(&m) ++ K, c := ek.key.EncapsulateInternal(&m) + sink ^= c[0] ^ K[0] + } + } +@@ -255,7 +255,7 @@ func BenchmarkDecaps(b *testing.B) { + b.Fatal(err) + } + ek := dk.EncapsulationKey() +- c, _ := ek.Encapsulate() ++ _, c := ek.Encapsulate() + b.ResetTimer() + for i := 0; i < b.N; i++ { + K, _ := dk.Decapsulate(c) +@@ -270,7 +270,7 @@ func BenchmarkRoundTrip(b *testing.B) { + } + ek := dk.EncapsulationKey() + ekBytes := ek.Bytes() +- c, _ := ek.Encapsulate() ++ _, c := ek.Encapsulate() + if err != nil { + b.Fatal(err) + } +@@ -296,7 +296,7 @@ func BenchmarkRoundTrip(b *testing.B) { + if err != nil { + b.Fatal(err) + } +- cS, Ks := ek.Encapsulate() ++ Ks, cS := ek.Encapsulate() + if err != nil { + b.Fatal(err) + } +diff --git a/src/crypto/pbkdf2/pbkdf2.go b/src/crypto/pbkdf2/pbkdf2.go +index 0fdd9e822d..d40daab5e5 100644 +--- a/src/crypto/pbkdf2/pbkdf2.go ++++ b/src/crypto/pbkdf2/pbkdf2.go +@@ -2,20 +2,12 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-/* +-Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC +-2898 / PKCS #5 v2.0. +- +-A key derivation function is useful when encrypting data based on a password +-or any other not-fully-random data. It uses a pseudorandom function to derive +-a secure encryption key based on the password. +- +-While v2.0 of the standard defines only one pseudorandom function to use, +-HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved +-Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To +-choose, you can pass the `New` functions from the different SHA packages to +-pbkdf2.Key. +-*/ ++// Package pbkdf2 implements the key derivation function PBKDF2 as defined in ++// RFC 8018 (PKCS #5 v2.1). ++// ++// A key derivation function is useful when encrypting data based on a password ++// or any other not-fully-random data. It uses a pseudorandom function to derive ++// a secure encryption key based on the password. + package pbkdf2 + + import ( +diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go +index 2474ab82df..2535661040 100644 +--- a/src/crypto/rsa/rsa_test.go ++++ b/src/crypto/rsa/rsa_test.go +@@ -101,7 +101,7 @@ func TestImpossibleKeyGeneration(t *testing.T) { + // This test ensures that trying to generate or validate toy RSA keys + // doesn't enter an infinite loop or panic. + t.Setenv("GODEBUG", "rsa1024min=0") +- for i := 0; i < 128; i++ { ++ for i := 0; i < 32; i++ { + GenerateKey(rand.Reader, i) + GenerateMultiPrimeKey(rand.Reader, 3, i) + GenerateMultiPrimeKey(rand.Reader, 4, i) +@@ -184,7 +184,7 @@ func TestEverything(t *testing.T) { + } + + t.Setenv("GODEBUG", "rsa1024min=0") +- min := 128 ++ min := 32 + max := 560 // any smaller than this and not all tests will run + if *allFlag { + max = 2048 +diff --git a/src/crypto/tls/bogo_config.json b/src/crypto/tls/bogo_config.json +index 1c313ec81e..32969a3fb5 100644 +--- a/src/crypto/tls/bogo_config.json ++++ b/src/crypto/tls/bogo_config.json +@@ -246,5 +246,8 @@ + 25, + 29, + 4588 +- ] ++ ], ++ "ErrorMap": { ++ ":ECH_REJECTED:": "tls: server rejected ECH" ++ } + } +diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go +index f98d24b879..d6942d2ef1 100644 +--- a/src/crypto/tls/common.go ++++ b/src/crypto/tls/common.go +@@ -456,7 +456,7 @@ type ClientHelloInfo struct { + SupportedVersions []uint16 + + // Extensions lists the IDs of the extensions presented by the client +- // in the client hello. ++ // in the ClientHello. + Extensions []uint16 + + // Conn is the underlying net.Conn for the connection. Do not read +@@ -821,7 +821,7 @@ type Config struct { + + // EncryptedClientHelloRejectionVerify, if not nil, is called when ECH is + // rejected by the remote server, in order to verify the ECH provider +- // certificate in the outer Client Hello. If it returns a non-nil error, the ++ // certificate in the outer ClientHello. If it returns a non-nil error, the + // handshake is aborted and that error results. + // + // On the server side this field is not used. +diff --git a/src/crypto/tls/ech.go b/src/crypto/tls/ech.go +index 55d52179c2..d9795b4ee2 100644 +--- a/src/crypto/tls/ech.go ++++ b/src/crypto/tls/ech.go +@@ -378,7 +378,7 @@ func decodeInnerClientHello(outer *clientHelloMsg, encoded []byte) (*clientHello + } + + if !bytes.Equal(inner.encryptedClientHello, []byte{uint8(innerECHExt)}) { +- return nil, errors.New("tls: client sent invalid encrypted_client_hello extension") ++ return nil, errInvalidECHExt + } + + if len(inner.supportedVersions) != 1 || (len(inner.supportedVersions) >= 1 && inner.supportedVersions[0] != VersionTLS13) { +@@ -481,6 +481,7 @@ func (e *ECHRejectionError) Error() string { + } + + var errMalformedECHExt = errors.New("tls: malformed encrypted_client_hello extension") ++var errInvalidECHExt = errors.New("tls: client sent invalid encrypted_client_hello extension") + + type echExtType uint8 + +@@ -507,7 +508,7 @@ func parseECHExt(ext []byte) (echType echExtType, cs echCipher, configID uint8, + return echType, cs, 0, nil, nil, nil + } + if echType != outerECHExt { +- err = errMalformedECHExt ++ err = errInvalidECHExt + return + } + if !s.ReadUint16(&cs.KDFID) { +@@ -549,8 +550,13 @@ func marshalEncryptedClientHelloConfigList(configs []EncryptedClientHelloKey) ([ + func (c *Conn) processECHClientHello(outer *clientHelloMsg) (*clientHelloMsg, *echServerContext, error) { + echType, echCiphersuite, configID, encap, payload, err := parseECHExt(outer.encryptedClientHello) + if err != nil { +- c.sendAlert(alertDecodeError) +- return nil, nil, errors.New("tls: client sent invalid encrypted_client_hello extension") ++ if errors.Is(err, errInvalidECHExt) { ++ c.sendAlert(alertIllegalParameter) ++ } else { ++ c.sendAlert(alertDecodeError) ++ } ++ ++ return nil, nil, errInvalidECHExt + } + + if echType == innerECHExt { +@@ -597,7 +603,7 @@ func (c *Conn) processECHClientHello(outer *clientHelloMsg) (*clientHelloMsg, *e + echInner, err := decodeInnerClientHello(outer, encodedInner) + if err != nil { + c.sendAlert(alertIllegalParameter) +- return nil, nil, errors.New("tls: client sent invalid encrypted_client_hello extension") ++ return nil, nil, errInvalidECHExt + } + + c.echAccepted = true +diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go +index ecc62ff2ed..38bd417a0d 100644 +--- a/src/crypto/tls/handshake_client.go ++++ b/src/crypto/tls/handshake_client.go +@@ -260,6 +260,7 @@ type echClientContext struct { + kdfID uint16 + aeadID uint16 + echRejected bool ++ retryConfigs []byte + } + + func (c *Conn) clientHandshake(ctx context.Context) (err error) { +@@ -944,7 +945,7 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { + } + + // checkALPN ensure that the server's choice of ALPN protocol is compatible with +-// the protocols that we advertised in the Client Hello. ++// the protocols that we advertised in the ClientHello. + func checkALPN(clientProtos []string, serverProto string, quic bool) error { + if serverProto == "" { + if quic && len(clientProtos) > 0 { +diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go +index bb164bba55..bc54475fa4 100644 +--- a/src/crypto/tls/handshake_client_test.go ++++ b/src/crypto/tls/handshake_client_test.go +@@ -856,6 +856,7 @@ func testResumption(t *testing.T, version uint16) { + MaxVersion: version, + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, + Certificates: testCertificates, ++ Time: testTime, + } + + issuer, err := x509.ParseCertificate(testRSA2048CertificateIssuer) +@@ -872,6 +873,7 @@ func testResumption(t *testing.T, version uint16) { + ClientSessionCache: NewLRUClientSessionCache(32), + RootCAs: rootCAs, + ServerName: "example.golang", ++ Time: testTime, + } + + testResumeState := func(test string, didResume bool) { +@@ -918,7 +920,7 @@ func testResumption(t *testing.T, version uint16) { + + // An old session ticket is replaced with a ticket encrypted with a fresh key. + ticket = getTicket() +- serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } ++ serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) } + testResumeState("ResumeWithOldTicket", true) + if bytes.Equal(ticket, getTicket()) { + t.Fatal("old first ticket matches the fresh one") +@@ -926,13 +928,13 @@ func testResumption(t *testing.T, version uint16) { + + // Once the session master secret is expired, a full handshake should occur. + ticket = getTicket() +- serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } ++ serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + time.Minute) } + testResumeState("ResumeWithExpiredTicket", false) + if bytes.Equal(ticket, getTicket()) { + t.Fatal("expired first ticket matches the fresh one") + } + +- serverConfig.Time = func() time.Time { return time.Now() } // reset the time back ++ serverConfig.Time = testTime // reset the time back + key1 := randomKey() + serverConfig.SetSessionTicketKeys([][32]byte{key1}) + +@@ -949,11 +951,11 @@ func testResumption(t *testing.T, version uint16) { + testResumeState("KeyChangeFinish", true) + + // Age the session ticket a bit, but not yet expired. +- serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } ++ serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) } + testResumeState("OldSessionTicket", true) + ticket = getTicket() + // Expire the session ticket, which would force a full handshake. +- serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } ++ serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + 2*time.Minute) } + testResumeState("ExpiredSessionTicket", false) + if bytes.Equal(ticket, getTicket()) { + t.Fatal("new ticket wasn't provided after old ticket expired") +@@ -961,7 +963,7 @@ func testResumption(t *testing.T, version uint16) { + + // Age the session ticket a bit at a time, but don't expire it. + d := 0 * time.Hour +- serverConfig.Time = func() time.Time { return time.Now().Add(d) } ++ serverConfig.Time = func() time.Time { return testTime().Add(d) } + deleteTicket() + testResumeState("GetFreshSessionTicket", false) + for i := 0; i < 13; i++ { +@@ -972,7 +974,7 @@ func testResumption(t *testing.T, version uint16) { + // handshake occurs for TLS 1.2. Resumption should still occur for + // TLS 1.3 since the client should be using a fresh ticket sent over + // by the server. +- d += 12 * time.Hour ++ d += 12*time.Hour + time.Minute + if version == VersionTLS13 { + testResumeState("ExpiredSessionTicket", true) + } else { +@@ -988,6 +990,7 @@ func testResumption(t *testing.T, version uint16) { + MaxVersion: version, + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, + Certificates: testCertificates, ++ Time: testTime, + } + serverConfig.SetSessionTicketKeys([][32]byte{key2}) + +@@ -1013,6 +1016,7 @@ func testResumption(t *testing.T, version uint16) { + CurvePreferences: []CurveID{CurveP521, CurveP384, CurveP256}, + MaxVersion: version, + Certificates: testCertificates, ++ Time: testTime, + } + testResumeState("InitialHandshake", false) + testResumeState("WithHelloRetryRequest", true) +@@ -1022,6 +1026,7 @@ func testResumption(t *testing.T, version uint16) { + MaxVersion: version, + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, + Certificates: testCertificates, ++ Time: testTime, + } + } + +@@ -1743,6 +1748,7 @@ func testVerifyConnection(t *testing.T, version uint16) { + serverConfig := &Config{ + MaxVersion: version, + Certificates: testCertificates, ++ Time: testTime, + ClientCAs: rootCAs, + NextProtos: []string{"protocol1"}, + } +@@ -1756,6 +1762,7 @@ func testVerifyConnection(t *testing.T, version uint16) { + RootCAs: rootCAs, + ServerName: "example.golang", + Certificates: testCertificates, ++ Time: testTime, + NextProtos: []string{"protocol1"}, + } + test.configureClient(clientConfig, &clientCalled) +@@ -1799,8 +1806,6 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { + rootCAs := x509.NewCertPool() + rootCAs.AddCert(issuer) + +- now := func() time.Time { return time.Unix(1476984729, 0) } +- + sentinelErr := errors.New("TestVerifyPeerCertificate") + + verifyPeerCertificateCallback := func(called *bool, rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { +@@ -2046,7 +2051,7 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { + config.ServerName = "example.golang" + config.ClientAuth = RequireAndVerifyClientCert + config.ClientCAs = rootCAs +- config.Time = now ++ config.Time = testTime + config.MaxVersion = version + config.Certificates = make([]Certificate, 1) + config.Certificates[0].Certificate = [][]byte{testRSA2048Certificate} +@@ -2064,7 +2069,7 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { + config.Certificates = []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} + config.ServerName = "example.golang" + config.RootCAs = rootCAs +- config.Time = now ++ config.Time = testTime + config.MaxVersion = version + test.configureClient(config, &clientCalled) + clientErr := Client(c, config).Handshake() +@@ -2379,7 +2384,7 @@ func testGetClientCertificate(t *testing.T, version uint16) { + serverConfig.RootCAs = x509.NewCertPool() + serverConfig.RootCAs.AddCert(issuer) + serverConfig.ClientCAs = serverConfig.RootCAs +- serverConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } ++ serverConfig.Time = testTime + serverConfig.MaxVersion = version + + clientConfig := testConfig.Clone() +@@ -2562,6 +2567,7 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) { + ClientSessionCache: NewLRUClientSessionCache(32), + ServerName: "example.golang", + RootCAs: roots, ++ Time: testTime, + } + serverConfig := testConfig.Clone() + serverConfig.Certificates = []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} +diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go +index 38c6025db7..c0396e7579 100644 +--- a/src/crypto/tls/handshake_client_tls13.go ++++ b/src/crypto/tls/handshake_client_tls13.go +@@ -85,7 +85,6 @@ func (hs *clientHandshakeStateTLS13) handshake() error { + } + } + +- var echRetryConfigList []byte + if hs.echContext != nil { + confTranscript := cloneHash(hs.echContext.innerTranscript, hs.suite.hash) + confTranscript.Write(hs.serverHello.original[:30]) +@@ -114,9 +113,6 @@ func (hs *clientHandshakeStateTLS13) handshake() error { + } + } else { + hs.echContext.echRejected = true +- // If the server sent us retry configs, we'll return these to +- // the user so they can update their Config. +- echRetryConfigList = hs.serverHello.encryptedClientHello + } + } + +@@ -155,7 +151,7 @@ func (hs *clientHandshakeStateTLS13) handshake() error { + + if hs.echContext != nil && hs.echContext.echRejected { + c.sendAlert(alertECHRequired) +- return &ECHRejectionError{echRetryConfigList} ++ return &ECHRejectionError{hs.echContext.retryConfigs} + } + + c.isHandshakeComplete.Store(true) +@@ -601,9 +597,13 @@ func (hs *clientHandshakeStateTLS13) readServerParameters() error { + return errors.New("tls: server accepted 0-RTT with the wrong ALPN") + } + } +- if hs.echContext != nil && !hs.echContext.echRejected && encryptedExtensions.echRetryConfigs != nil { +- c.sendAlert(alertUnsupportedExtension) +- return errors.New("tls: server sent encrypted client hello retry configs after accepting encrypted client hello") ++ if hs.echContext != nil { ++ if hs.echContext.echRejected { ++ hs.echContext.retryConfigs = encryptedExtensions.echRetryConfigs ++ } else if encryptedExtensions.echRetryConfigs != nil { ++ c.sendAlert(alertUnsupportedExtension) ++ return errors.New("tls: server sent encrypted client hello retry configs after accepting encrypted client hello") ++ } + } + + return nil +diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go +index fa00d7b741..6c6141c421 100644 +--- a/src/crypto/tls/handshake_messages.go ++++ b/src/crypto/tls/handshake_messages.go +@@ -97,7 +97,7 @@ type clientHelloMsg struct { + pskBinders [][]byte + quicTransportParameters []byte + encryptedClientHello []byte +- // extensions are only populated on the servers-ide of a handshake ++ // extensions are only populated on the server-side of a handshake + extensions []uint16 + } + +diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go +index 29a802d54b..f533023afb 100644 +--- a/src/crypto/tls/handshake_server_test.go ++++ b/src/crypto/tls/handshake_server_test.go +@@ -519,6 +519,7 @@ func testCrossVersionResume(t *testing.T, version uint16) { + serverConfig := &Config{ + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, + Certificates: testConfig.Certificates, ++ Time: testTime, + } + clientConfig := &Config{ + CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, +@@ -526,6 +527,7 @@ func testCrossVersionResume(t *testing.T, version uint16) { + ClientSessionCache: NewLRUClientSessionCache(1), + ServerName: "servername", + MinVersion: VersionTLS12, ++ Time: testTime, + } + + // Establish a session at TLS 1.3. +diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go +index 3552d89ba3..76fff6974e 100644 +--- a/src/crypto/tls/handshake_server_tls13.go ++++ b/src/crypto/tls/handshake_server_tls13.go +@@ -280,7 +280,7 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { + c.sendAlert(alertIllegalParameter) + return errors.New("tls: invalid X25519MLKEM768 client key share") + } +- ciphertext, mlkemSharedSecret := k.Encapsulate() ++ mlkemSharedSecret, ciphertext := k.Encapsulate() + // draft-kwiatkowski-tls-ecdhe-mlkem-02, Section 3.1.3: "For + // X25519MLKEM768, the shared secret is the concatenation of the ML-KEM + // shared secret and the X25519 shared secret. The shared secret is 64 +diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go +index 5a9c24fb83..ea8ac6fc83 100644 +--- a/src/crypto/tls/handshake_test.go ++++ b/src/crypto/tls/handshake_test.go +@@ -522,6 +522,11 @@ func fromHex(s string) []byte { + return b + } + ++// testTime is 2016-10-20T17:32:09.000Z, which is within the validity period of ++// [testRSACertificate], [testRSACertificateIssuer], [testRSA2048Certificate], ++// [testRSA2048CertificateIssuer], and [testECDSACertificate]. ++var testTime = func() time.Time { return time.Unix(1476984729, 0) } ++ + var testRSACertificate = fromHex("3082024b308201b4a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301a310b3009060355040a1302476f310b300906035504031302476f30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a38193308190300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b30190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b0500038181009d30cc402b5b50a061cbbae55358e1ed8328a9581aa938a495a1ac315a1a84663d43d32dd90bf297dfd320643892243a00bccf9c7db74020015faad3166109a276fd13c3cce10c5ceeb18782f16c04ed73bbb343778d0c1cf10fa1d8408361c94c722b9daedb4606064df4c1b33ec0d1bd42d4dbfe3d1360845c21d33be9fae7") + + var testRSACertificateIssuer = fromHex("3082021930820182a003020102020900ca5e4e811a965964300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f7430819f300d06092a864886f70d010101050003818d0030818902818100d667b378bb22f34143b6cd2008236abefaf2852adf3ab05e01329e2c14834f5105df3f3073f99dab5442d45ee5f8f57b0111c8cb682fbb719a86944eebfffef3406206d898b8c1b1887797c9c5006547bb8f00e694b7a063f10839f269f2c34fff7a1f4b21fbcd6bfdfb13ac792d1d11f277b5c5b48600992203059f2a8f8cc50203010001a35d305b300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff30190603551d0e041204104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b050003818100c1154b4bab5266221f293766ae4138899bd4c5e36b13cee670ceeaa4cbdf4f6679017e2fe649765af545749fe4249418a56bd38a04b81e261f5ce86b8d5c65413156a50d12449554748c59a30c515bc36a59d38bddf51173e899820b282e40aa78c806526fd184fb6b4cf186ec728edffa585440d2b3225325f7ab580e87dd76") +diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go +index 51cd2b91bd..76a9a222a9 100644 +--- a/src/crypto/tls/tls_test.go ++++ b/src/crypto/tls/tls_test.go +@@ -1158,8 +1158,6 @@ func TestConnectionState(t *testing.T) { + rootCAs := x509.NewCertPool() + rootCAs.AddCert(issuer) + +- now := func() time.Time { return time.Unix(1476984729, 0) } +- + const alpnProtocol = "golang" + const serverName = "example.golang" + var scts = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")} +@@ -1175,7 +1173,7 @@ func TestConnectionState(t *testing.T) { + } + t.Run(name, func(t *testing.T) { + config := &Config{ +- Time: now, ++ Time: testTime, + Rand: zeroSource{}, + Certificates: make([]Certificate, 1), + MaxVersion: v, +@@ -1810,7 +1808,7 @@ func testVerifyCertificates(t *testing.T, version uint16) { + var serverVerifyPeerCertificates, clientVerifyPeerCertificates bool + + clientConfig := testConfig.Clone() +- clientConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } ++ clientConfig.Time = testTime + clientConfig.MaxVersion = version + clientConfig.MinVersion = version + clientConfig.RootCAs = rootCAs +diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go +index 958ed9971d..89bd70b5b2 100644 +--- a/src/debug/elf/file.go ++++ b/src/debug/elf/file.go +@@ -209,22 +209,13 @@ type Symbol struct { + Name string + Info, Other byte + +- // VersionScope describes the version in which the symbol is defined. +- // This is only set for the dynamic symbol table. +- // When no symbol versioning information is available, +- // this is VersionScopeNone. +- VersionScope SymbolVersionScope +- // VersionIndex is the version index. +- // This is only set if VersionScope is VersionScopeSpecific or +- // VersionScopeHidden. This is only set for the dynamic symbol table. +- // This index will match either [DynamicVersion.Index] +- // in the slice returned by [File.DynamicVersions], +- // or [DynamicVersiondep.Index] in the Needs field +- // of the elements of the slice returned by [File.DynamicVersionNeeds]. +- // In general, a defined symbol will have an index referring +- // to DynamicVersions, and an undefined symbol will have an index +- // referring to some version in DynamicVersionNeeds. +- VersionIndex int16 ++ // HasVersion reports whether the symbol has any version information. ++ // This will only be true for the dynamic symbol table. ++ HasVersion bool ++ // VersionIndex is the symbol's version index. ++ // Use the methods of the [VersionIndex] type to access it. ++ // This field is only meaningful if HasVersion is true. ++ VersionIndex VersionIndex + + Section SectionIndex + Value, Size uint64 +@@ -678,7 +669,6 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { + symbols[i].Name = str + symbols[i].Info = sym.Info + symbols[i].Other = sym.Other +- symbols[i].VersionIndex = -1 + symbols[i].Section = SectionIndex(sym.Shndx) + symbols[i].Value = uint64(sym.Value) + symbols[i].Size = uint64(sym.Size) +@@ -726,7 +716,6 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) { + symbols[i].Name = str + symbols[i].Info = sym.Info + symbols[i].Other = sym.Other +- symbols[i].VersionIndex = -1 + symbols[i].Section = SectionIndex(sym.Shndx) + symbols[i].Value = sym.Value + symbols[i].Size = sym.Size +@@ -1473,7 +1462,7 @@ func (f *File) DynamicSymbols() ([]Symbol, error) { + } + if hasVersions { + for i := range sym { +- sym[i].VersionIndex, sym[i].Version, sym[i].Library, sym[i].VersionScope = f.gnuVersion(i) ++ sym[i].HasVersion, sym[i].VersionIndex, sym[i].Version, sym[i].Library = f.gnuVersion(i) + } + } + return sym, nil +@@ -1502,23 +1491,37 @@ func (f *File) ImportedSymbols() ([]ImportedSymbol, error) { + if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF { + all = append(all, ImportedSymbol{Name: s.Name}) + sym := &all[len(all)-1] +- _, sym.Version, sym.Library, _ = f.gnuVersion(i) ++ _, _, sym.Version, sym.Library = f.gnuVersion(i) + } + } + return all, nil + } + +-// SymbolVersionScope describes the version in which a [Symbol] is defined. +-// This is only used for the dynamic symbol table. +-type SymbolVersionScope byte ++// VersionIndex is the type of a [Symbol] version index. ++type VersionIndex uint16 + +-const ( +- VersionScopeNone SymbolVersionScope = iota // no symbol version available +- VersionScopeLocal // symbol has local scope +- VersionScopeGlobal // symbol has global scope and is in the base version +- VersionScopeSpecific // symbol has global scope and is in the version given by VersionIndex +- VersionScopeHidden // symbol is in the version given by VersionIndex, and is hidden +-) ++// IsHidden reports whether the symbol is hidden within the version. ++// This means that the symbol can only be seen by specifying the exact version. ++func (vi VersionIndex) IsHidden() bool { ++ return vi&0x8000 != 0 ++} ++ ++// Index returns the version index. ++// If this is the value 0, it means that the symbol is local, ++// and is not visible externally. ++// If this is the value 1, it means that the symbol is in the base version, ++// and has no specific version; it may or may not match a ++// [DynamicVersion.Index] in the slice returned by [File.DynamicVersions]. ++// Other values will match either [DynamicVersion.Index] ++// in the slice returned by [File.DynamicVersions], ++// or [DynamicVersionDep.Index] in the Needs field ++// of the elements of the slice returned by [File.DynamicVersionNeeds]. ++// In general, a defined symbol will have an index referring ++// to DynamicVersions, and an undefined symbol will have an index ++// referring to some version in DynamicVersionNeeds. ++func (vi VersionIndex) Index() uint16 { ++ return uint16(vi & 0x7fff) ++} + + // DynamicVersion is a version defined by a dynamic object. + // This describes entries in the ELF SHT_GNU_verdef section. +@@ -1752,45 +1755,38 @@ func (f *File) gnuVersionInit(str []byte) (bool, error) { + + // gnuVersion adds Library and Version information to sym, + // which came from offset i of the symbol table. +-func (f *File) gnuVersion(i int) (versionIndex int16, version string, library string, versionFlags SymbolVersionScope) { ++func (f *File) gnuVersion(i int) (hasVersion bool, versionIndex VersionIndex, version string, library string) { + // Each entry is two bytes; skip undef entry at beginning. + i = (i + 1) * 2 + if i >= len(f.gnuVersym) { +- return -1, "", "", VersionScopeNone ++ return false, 0, "", "" + } + s := f.gnuVersym[i:] + if len(s) < 2 { +- return -1, "", "", VersionScopeNone +- } +- j := int32(f.ByteOrder.Uint16(s)) +- ndx := int16(j & 0x7fff) +- +- if j == 0 { +- return ndx, "", "", VersionScopeLocal +- } else if j == 1 { +- return ndx, "", "", VersionScopeGlobal ++ return false, 0, "", "" + } ++ vi := VersionIndex(f.ByteOrder.Uint16(s)) ++ ndx := vi.Index() + +- scope := VersionScopeSpecific +- if j&0x8000 != 0 { +- scope = VersionScopeHidden ++ if ndx == 0 || ndx == 1 { ++ return true, vi, "", "" + } + + for _, v := range f.dynVerNeeds { + for _, n := range v.Needs { +- if uint16(ndx) == n.Index { +- return ndx, n.Dep, v.Name, scope ++ if ndx == n.Index { ++ return true, vi, n.Dep, v.Name + } + } + } + + for _, v := range f.dynVers { +- if uint16(ndx) == v.Index { +- return ndx, v.Name, "", scope ++ if ndx == v.Index { ++ return true, vi, v.Name, "" + } + } + +- return -1, "", "", VersionScopeNone ++ return false, 0, "", "" + } + + // ImportedLibraries returns the names of all libraries +diff --git a/src/debug/elf/file_test.go b/src/debug/elf/file_test.go +index 72e4558868..1fdbbad04d 100644 +--- a/src/debug/elf/file_test.go ++++ b/src/debug/elf/file_test.go +@@ -78,80 +78,80 @@ var fileTests = []fileTest{ + }, + []string{"libc.so.6"}, + []Symbol{ +- {"", 3, 0, VersionScopeNone, -1, 1, 134512852, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 2, 134512876, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 3, 134513020, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 4, 134513292, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 5, 134513480, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 6, 134513512, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 7, 134513532, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 8, 134513612, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 9, 134513996, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 10, 134514008, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 11, 134518268, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 12, 134518280, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 13, 134518284, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 14, 134518436, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 15, 134518444, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 16, 134518452, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 17, 134518456, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 18, 134518484, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 19, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 20, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 21, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 22, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 23, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 24, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 25, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 26, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 27, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 28, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 29, 0, 0, "", ""}, +- {"crt1.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"__CTOR_LIST__", 1, 0, VersionScopeNone, -1, 14, 134518436, 0, "", ""}, +- {"__DTOR_LIST__", 1, 0, VersionScopeNone, -1, 15, 134518444, 0, "", ""}, +- {"__EH_FRAME_BEGIN__", 1, 0, VersionScopeNone, -1, 12, 134518280, 0, "", ""}, +- {"__JCR_LIST__", 1, 0, VersionScopeNone, -1, 16, 134518452, 0, "", ""}, +- {"p.0", 1, 0, VersionScopeNone, -1, 11, 134518276, 0, "", ""}, +- {"completed.1", 1, 0, VersionScopeNone, -1, 18, 134518484, 1, "", ""}, +- {"__do_global_dtors_aux", 2, 0, VersionScopeNone, -1, 8, 134513760, 0, "", ""}, +- {"object.2", 1, 0, VersionScopeNone, -1, 18, 134518488, 24, "", ""}, +- {"frame_dummy", 2, 0, VersionScopeNone, -1, 8, 134513836, 0, "", ""}, +- {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"__CTOR_END__", 1, 0, VersionScopeNone, -1, 14, 134518440, 0, "", ""}, +- {"__DTOR_END__", 1, 0, VersionScopeNone, -1, 15, 134518448, 0, "", ""}, +- {"__FRAME_END__", 1, 0, VersionScopeNone, -1, 12, 134518280, 0, "", ""}, +- {"__JCR_END__", 1, 0, VersionScopeNone, -1, 16, 134518452, 0, "", ""}, +- {"__do_global_ctors_aux", 2, 0, VersionScopeNone, -1, 8, 134513960, 0, "", ""}, +- {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"printf", 18, 0, VersionScopeNone, -1, 0, 0, 44, "", ""}, +- {"_DYNAMIC", 17, 0, VersionScopeNone, -1, 65521, 134518284, 0, "", ""}, +- {"__dso_handle", 17, 2, VersionScopeNone, -1, 11, 134518272, 0, "", ""}, +- {"_init", 18, 0, VersionScopeNone, -1, 6, 134513512, 0, "", ""}, +- {"environ", 17, 0, VersionScopeNone, -1, 18, 134518512, 4, "", ""}, +- {"__deregister_frame_info", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, +- {"__progname", 17, 0, VersionScopeNone, -1, 11, 134518268, 4, "", ""}, +- {"_start", 18, 0, VersionScopeNone, -1, 8, 134513612, 145, "", ""}, +- {"__bss_start", 16, 0, VersionScopeNone, -1, 65521, 134518484, 0, "", ""}, +- {"main", 18, 0, VersionScopeNone, -1, 8, 134513912, 46, "", ""}, +- {"_init_tls", 18, 0, VersionScopeNone, -1, 0, 0, 5, "", ""}, +- {"_fini", 18, 0, VersionScopeNone, -1, 9, 134513996, 0, "", ""}, +- {"atexit", 18, 0, VersionScopeNone, -1, 0, 0, 43, "", ""}, +- {"_edata", 16, 0, VersionScopeNone, -1, 65521, 134518484, 0, "", ""}, +- {"_GLOBAL_OFFSET_TABLE_", 17, 0, VersionScopeNone, -1, 65521, 134518456, 0, "", ""}, +- {"_end", 16, 0, VersionScopeNone, -1, 65521, 134518516, 0, "", ""}, +- {"exit", 18, 0, VersionScopeNone, -1, 0, 0, 68, "", ""}, +- {"_Jv_RegisterClasses", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, +- {"__register_frame_info", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 1, 134512852, 0, "", ""}, ++ {"", 3, 0, false, 0, 2, 134512876, 0, "", ""}, ++ {"", 3, 0, false, 0, 3, 134513020, 0, "", ""}, ++ {"", 3, 0, false, 0, 4, 134513292, 0, "", ""}, ++ {"", 3, 0, false, 0, 5, 134513480, 0, "", ""}, ++ {"", 3, 0, false, 0, 6, 134513512, 0, "", ""}, ++ {"", 3, 0, false, 0, 7, 134513532, 0, "", ""}, ++ {"", 3, 0, false, 0, 8, 134513612, 0, "", ""}, ++ {"", 3, 0, false, 0, 9, 134513996, 0, "", ""}, ++ {"", 3, 0, false, 0, 10, 134514008, 0, "", ""}, ++ {"", 3, 0, false, 0, 11, 134518268, 0, "", ""}, ++ {"", 3, 0, false, 0, 12, 134518280, 0, "", ""}, ++ {"", 3, 0, false, 0, 13, 134518284, 0, "", ""}, ++ {"", 3, 0, false, 0, 14, 134518436, 0, "", ""}, ++ {"", 3, 0, false, 0, 15, 134518444, 0, "", ""}, ++ {"", 3, 0, false, 0, 16, 134518452, 0, "", ""}, ++ {"", 3, 0, false, 0, 17, 134518456, 0, "", ""}, ++ {"", 3, 0, false, 0, 18, 134518484, 0, "", ""}, ++ {"", 3, 0, false, 0, 19, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 20, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 21, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 22, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 23, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 24, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 25, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 26, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 27, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 28, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 29, 0, 0, "", ""}, ++ {"crt1.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"__CTOR_LIST__", 1, 0, false, 0, 14, 134518436, 0, "", ""}, ++ {"__DTOR_LIST__", 1, 0, false, 0, 15, 134518444, 0, "", ""}, ++ {"__EH_FRAME_BEGIN__", 1, 0, false, 0, 12, 134518280, 0, "", ""}, ++ {"__JCR_LIST__", 1, 0, false, 0, 16, 134518452, 0, "", ""}, ++ {"p.0", 1, 0, false, 0, 11, 134518276, 0, "", ""}, ++ {"completed.1", 1, 0, false, 0, 18, 134518484, 1, "", ""}, ++ {"__do_global_dtors_aux", 2, 0, false, 0, 8, 134513760, 0, "", ""}, ++ {"object.2", 1, 0, false, 0, 18, 134518488, 24, "", ""}, ++ {"frame_dummy", 2, 0, false, 0, 8, 134513836, 0, "", ""}, ++ {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"__CTOR_END__", 1, 0, false, 0, 14, 134518440, 0, "", ""}, ++ {"__DTOR_END__", 1, 0, false, 0, 15, 134518448, 0, "", ""}, ++ {"__FRAME_END__", 1, 0, false, 0, 12, 134518280, 0, "", ""}, ++ {"__JCR_END__", 1, 0, false, 0, 16, 134518452, 0, "", ""}, ++ {"__do_global_ctors_aux", 2, 0, false, 0, 8, 134513960, 0, "", ""}, ++ {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"printf", 18, 0, false, 0, 0, 0, 44, "", ""}, ++ {"_DYNAMIC", 17, 0, false, 0, 65521, 134518284, 0, "", ""}, ++ {"__dso_handle", 17, 2, false, 0, 11, 134518272, 0, "", ""}, ++ {"_init", 18, 0, false, 0, 6, 134513512, 0, "", ""}, ++ {"environ", 17, 0, false, 0, 18, 134518512, 4, "", ""}, ++ {"__deregister_frame_info", 32, 0, false, 0, 0, 0, 0, "", ""}, ++ {"__progname", 17, 0, false, 0, 11, 134518268, 4, "", ""}, ++ {"_start", 18, 0, false, 0, 8, 134513612, 145, "", ""}, ++ {"__bss_start", 16, 0, false, 0, 65521, 134518484, 0, "", ""}, ++ {"main", 18, 0, false, 0, 8, 134513912, 46, "", ""}, ++ {"_init_tls", 18, 0, false, 0, 0, 0, 5, "", ""}, ++ {"_fini", 18, 0, false, 0, 9, 134513996, 0, "", ""}, ++ {"atexit", 18, 0, false, 0, 0, 0, 43, "", ""}, ++ {"_edata", 16, 0, false, 0, 65521, 134518484, 0, "", ""}, ++ {"_GLOBAL_OFFSET_TABLE_", 17, 0, false, 0, 65521, 134518456, 0, "", ""}, ++ {"_end", 16, 0, false, 0, 65521, 134518516, 0, "", ""}, ++ {"exit", 18, 0, false, 0, 0, 0, 68, "", ""}, ++ {"_Jv_RegisterClasses", 32, 0, false, 0, 0, 0, 0, "", ""}, ++ {"__register_frame_info", 32, 0, false, 0, 0, 0, 0, "", ""}, + }, + }, + { +@@ -208,79 +208,79 @@ var fileTests = []fileTest{ + }, + []string{"libc.so.6"}, + []Symbol{ +- {"", 3, 0, VersionScopeNone, -1, 1, 4194816, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 2, 4194844, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 3, 4194880, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 4, 4194920, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 5, 4194952, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 6, 4195048, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 7, 4195110, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 8, 4195120, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 9, 4195152, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 10, 4195176, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 11, 4195224, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 12, 4195248, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 13, 4195296, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 14, 4195732, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 15, 4195748, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 16, 4195768, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 17, 4195808, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 18, 6293128, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 19, 6293144, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 20, 6293160, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 21, 6293168, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 22, 6293584, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 23, 6293592, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 24, 6293632, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 25, 6293656, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 26, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 27, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 28, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 29, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 30, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 31, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 32, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 33, 0, 0, "", ""}, +- {"init.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"initfini.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"call_gmon_start", 2, 0, VersionScopeNone, -1, 13, 4195340, 0, "", ""}, +- {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"__CTOR_LIST__", 1, 0, VersionScopeNone, -1, 18, 6293128, 0, "", ""}, +- {"__DTOR_LIST__", 1, 0, VersionScopeNone, -1, 19, 6293144, 0, "", ""}, +- {"__JCR_LIST__", 1, 0, VersionScopeNone, -1, 20, 6293160, 0, "", ""}, +- {"__do_global_dtors_aux", 2, 0, VersionScopeNone, -1, 13, 4195376, 0, "", ""}, +- {"completed.6183", 1, 0, VersionScopeNone, -1, 25, 6293656, 1, "", ""}, +- {"p.6181", 1, 0, VersionScopeNone, -1, 24, 6293648, 0, "", ""}, +- {"frame_dummy", 2, 0, VersionScopeNone, -1, 13, 4195440, 0, "", ""}, +- {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"__CTOR_END__", 1, 0, VersionScopeNone, -1, 18, 6293136, 0, "", ""}, +- {"__DTOR_END__", 1, 0, VersionScopeNone, -1, 19, 6293152, 0, "", ""}, +- {"__FRAME_END__", 1, 0, VersionScopeNone, -1, 17, 4195968, 0, "", ""}, +- {"__JCR_END__", 1, 0, VersionScopeNone, -1, 20, 6293160, 0, "", ""}, +- {"__do_global_ctors_aux", 2, 0, VersionScopeNone, -1, 13, 4195680, 0, "", ""}, +- {"initfini.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"_GLOBAL_OFFSET_TABLE_", 1, 2, VersionScopeNone, -1, 23, 6293592, 0, "", ""}, +- {"__init_array_end", 0, 2, VersionScopeNone, -1, 18, 6293124, 0, "", ""}, +- {"__init_array_start", 0, 2, VersionScopeNone, -1, 18, 6293124, 0, "", ""}, +- {"_DYNAMIC", 1, 2, VersionScopeNone, -1, 21, 6293168, 0, "", ""}, +- {"data_start", 32, 0, VersionScopeNone, -1, 24, 6293632, 0, "", ""}, +- {"__libc_csu_fini", 18, 0, VersionScopeNone, -1, 13, 4195520, 2, "", ""}, +- {"_start", 18, 0, VersionScopeNone, -1, 13, 4195296, 0, "", ""}, +- {"__gmon_start__", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, +- {"_Jv_RegisterClasses", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, +- {"puts@@GLIBC_2.2.5", 18, 0, VersionScopeNone, -1, 0, 0, 396, "", ""}, +- {"_fini", 18, 0, VersionScopeNone, -1, 14, 4195732, 0, "", ""}, +- {"__libc_start_main@@GLIBC_2.2.5", 18, 0, VersionScopeNone, -1, 0, 0, 450, "", ""}, +- {"_IO_stdin_used", 17, 0, VersionScopeNone, -1, 15, 4195748, 4, "", ""}, +- {"__data_start", 16, 0, VersionScopeNone, -1, 24, 6293632, 0, "", ""}, +- {"__dso_handle", 17, 2, VersionScopeNone, -1, 24, 6293640, 0, "", ""}, +- {"__libc_csu_init", 18, 0, VersionScopeNone, -1, 13, 4195536, 137, "", ""}, +- {"__bss_start", 16, 0, VersionScopeNone, -1, 65521, 6293656, 0, "", ""}, +- {"_end", 16, 0, VersionScopeNone, -1, 65521, 6293664, 0, "", ""}, +- {"_edata", 16, 0, VersionScopeNone, -1, 65521, 6293656, 0, "", ""}, +- {"main", 18, 0, VersionScopeNone, -1, 13, 4195480, 27, "", ""}, +- {"_init", 18, 0, VersionScopeNone, -1, 11, 4195224, 0, "", ""}, ++ {"", 3, 0, false, 0, 1, 4194816, 0, "", ""}, ++ {"", 3, 0, false, 0, 2, 4194844, 0, "", ""}, ++ {"", 3, 0, false, 0, 3, 4194880, 0, "", ""}, ++ {"", 3, 0, false, 0, 4, 4194920, 0, "", ""}, ++ {"", 3, 0, false, 0, 5, 4194952, 0, "", ""}, ++ {"", 3, 0, false, 0, 6, 4195048, 0, "", ""}, ++ {"", 3, 0, false, 0, 7, 4195110, 0, "", ""}, ++ {"", 3, 0, false, 0, 8, 4195120, 0, "", ""}, ++ {"", 3, 0, false, 0, 9, 4195152, 0, "", ""}, ++ {"", 3, 0, false, 0, 10, 4195176, 0, "", ""}, ++ {"", 3, 0, false, 0, 11, 4195224, 0, "", ""}, ++ {"", 3, 0, false, 0, 12, 4195248, 0, "", ""}, ++ {"", 3, 0, false, 0, 13, 4195296, 0, "", ""}, ++ {"", 3, 0, false, 0, 14, 4195732, 0, "", ""}, ++ {"", 3, 0, false, 0, 15, 4195748, 0, "", ""}, ++ {"", 3, 0, false, 0, 16, 4195768, 0, "", ""}, ++ {"", 3, 0, false, 0, 17, 4195808, 0, "", ""}, ++ {"", 3, 0, false, 0, 18, 6293128, 0, "", ""}, ++ {"", 3, 0, false, 0, 19, 6293144, 0, "", ""}, ++ {"", 3, 0, false, 0, 20, 6293160, 0, "", ""}, ++ {"", 3, 0, false, 0, 21, 6293168, 0, "", ""}, ++ {"", 3, 0, false, 0, 22, 6293584, 0, "", ""}, ++ {"", 3, 0, false, 0, 23, 6293592, 0, "", ""}, ++ {"", 3, 0, false, 0, 24, 6293632, 0, "", ""}, ++ {"", 3, 0, false, 0, 25, 6293656, 0, "", ""}, ++ {"", 3, 0, false, 0, 26, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 27, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 28, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 29, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 30, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 31, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 32, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 33, 0, 0, "", ""}, ++ {"init.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"initfini.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"call_gmon_start", 2, 0, false, 0, 13, 4195340, 0, "", ""}, ++ {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"__CTOR_LIST__", 1, 0, false, 0, 18, 6293128, 0, "", ""}, ++ {"__DTOR_LIST__", 1, 0, false, 0, 19, 6293144, 0, "", ""}, ++ {"__JCR_LIST__", 1, 0, false, 0, 20, 6293160, 0, "", ""}, ++ {"__do_global_dtors_aux", 2, 0, false, 0, 13, 4195376, 0, "", ""}, ++ {"completed.6183", 1, 0, false, 0, 25, 6293656, 1, "", ""}, ++ {"p.6181", 1, 0, false, 0, 24, 6293648, 0, "", ""}, ++ {"frame_dummy", 2, 0, false, 0, 13, 4195440, 0, "", ""}, ++ {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"__CTOR_END__", 1, 0, false, 0, 18, 6293136, 0, "", ""}, ++ {"__DTOR_END__", 1, 0, false, 0, 19, 6293152, 0, "", ""}, ++ {"__FRAME_END__", 1, 0, false, 0, 17, 4195968, 0, "", ""}, ++ {"__JCR_END__", 1, 0, false, 0, 20, 6293160, 0, "", ""}, ++ {"__do_global_ctors_aux", 2, 0, false, 0, 13, 4195680, 0, "", ""}, ++ {"initfini.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"_GLOBAL_OFFSET_TABLE_", 1, 2, false, 0, 23, 6293592, 0, "", ""}, ++ {"__init_array_end", 0, 2, false, 0, 18, 6293124, 0, "", ""}, ++ {"__init_array_start", 0, 2, false, 0, 18, 6293124, 0, "", ""}, ++ {"_DYNAMIC", 1, 2, false, 0, 21, 6293168, 0, "", ""}, ++ {"data_start", 32, 0, false, 0, 24, 6293632, 0, "", ""}, ++ {"__libc_csu_fini", 18, 0, false, 0, 13, 4195520, 2, "", ""}, ++ {"_start", 18, 0, false, 0, 13, 4195296, 0, "", ""}, ++ {"__gmon_start__", 32, 0, false, 0, 0, 0, 0, "", ""}, ++ {"_Jv_RegisterClasses", 32, 0, false, 0, 0, 0, 0, "", ""}, ++ {"puts@@GLIBC_2.2.5", 18, 0, false, 0, 0, 0, 396, "", ""}, ++ {"_fini", 18, 0, false, 0, 14, 4195732, 0, "", ""}, ++ {"__libc_start_main@@GLIBC_2.2.5", 18, 0, false, 0, 0, 0, 450, "", ""}, ++ {"_IO_stdin_used", 17, 0, false, 0, 15, 4195748, 4, "", ""}, ++ {"__data_start", 16, 0, false, 0, 24, 6293632, 0, "", ""}, ++ {"__dso_handle", 17, 2, false, 0, 24, 6293640, 0, "", ""}, ++ {"__libc_csu_init", 18, 0, false, 0, 13, 4195536, 137, "", ""}, ++ {"__bss_start", 16, 0, false, 0, 65521, 6293656, 0, "", ""}, ++ {"_end", 16, 0, false, 0, 65521, 6293664, 0, "", ""}, ++ {"_edata", 16, 0, false, 0, 65521, 6293656, 0, "", ""}, ++ {"main", 18, 0, false, 0, 13, 4195480, 27, "", ""}, ++ {"_init", 18, 0, false, 0, 11, 4195224, 0, "", ""}, + }, + }, + { +@@ -338,21 +338,21 @@ var fileTests = []fileTest{ + []ProgHeader{}, + nil, + []Symbol{ +- {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 1, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 3, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 4, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 5, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 6, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 8, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 9, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 11, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 13, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 15, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 16, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 14, 0, 0, "", ""}, +- {"main", 18, 0, VersionScopeNone, -1, 1, 0, 23, "", ""}, +- {"puts", 16, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, ++ {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 1, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 3, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 4, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 5, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 6, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 8, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 9, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 11, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 13, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 15, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 16, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 14, 0, 0, "", ""}, ++ {"main", 18, 0, false, 0, 1, 0, 23, "", ""}, ++ {"puts", 16, 0, false, 0, 0, 0, 0, "", ""}, + }, + }, + { +@@ -384,21 +384,21 @@ var fileTests = []fileTest{ + []ProgHeader{}, + nil, + []Symbol{ +- {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 1, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 3, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 4, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 5, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 6, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 8, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 9, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 11, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 13, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 15, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 16, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 14, 0, 0, "", ""}, +- {"main", 18, 0, VersionScopeNone, -1, 1, 0, 27, "", ""}, +- {"puts", 16, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, ++ {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 1, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 3, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 4, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 5, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 6, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 8, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 9, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 11, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 13, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 15, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 16, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 14, 0, 0, "", ""}, ++ {"main", 18, 0, false, 0, 1, 0, 27, "", ""}, ++ {"puts", 16, 0, false, 0, 0, 0, 0, "", ""}, + }, + }, + { +@@ -430,21 +430,21 @@ var fileTests = []fileTest{ + []ProgHeader{}, + nil, + []Symbol{ +- {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 1, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 3, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 4, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 5, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 6, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 8, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 9, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 11, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 13, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 15, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 16, 0, 0, "", ""}, +- {"", 3, 0, VersionScopeNone, -1, 14, 0, 0, "", ""}, +- {"main", 18, 0, VersionScopeNone, -1, 1, 0, 44, "", ""}, +- {"puts", 16, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, ++ {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 1, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 3, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 4, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 5, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 6, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 8, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 9, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 11, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 13, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 15, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 16, 0, 0, "", ""}, ++ {"", 3, 0, false, 0, 14, 0, 0, "", ""}, ++ {"main", 18, 0, false, 0, 1, 0, 44, "", ""}, ++ {"puts", 16, 0, false, 0, 0, 0, 0, "", ""}, + }, + }, + } +diff --git a/src/debug/elf/symbols_test.go b/src/debug/elf/symbols_test.go +index 8b6dac019b..6053d99acc 100644 +--- a/src/debug/elf/symbols_test.go ++++ b/src/debug/elf/symbols_test.go +@@ -39,6 +39,19 @@ func TestSymbols(t *testing.T) { + if !reflect.DeepEqual(ts, fs) { + t.Errorf("%s: Symbols = %v, want %v", file, fs, ts) + } ++ ++ for i, s := range fs { ++ if s.HasVersion { ++ // No hidden versions here. ++ if s.VersionIndex.IsHidden() { ++ t.Errorf("%s: symbol %d: unexpected hidden version", file, i) ++ } ++ if got, want := s.VersionIndex.Index(), uint16(s.VersionIndex); got != want { ++ t.Errorf("%s: symbol %d: VersionIndex.Index() == %d, want %d", file, i, got, want) ++ } ++ } ++ } ++ + } + for file, ts := range symbolsGolden { + do(file, ts, (*File).Symbols) +@@ -56,8 +69,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x1, + Value: 0x400200, + Size: 0x0, +@@ -66,8 +79,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x2, + Value: 0x40021C, + Size: 0x0, +@@ -76,8 +89,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x3, + Value: 0x400240, + Size: 0x0, +@@ -86,8 +99,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x4, + Value: 0x400268, + Size: 0x0, +@@ -96,8 +109,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x5, + Value: 0x400288, + Size: 0x0, +@@ -106,8 +119,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x6, + Value: 0x4002E8, + Size: 0x0, +@@ -116,8 +129,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x7, + Value: 0x400326, + Size: 0x0, +@@ -126,8 +139,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x8, + Value: 0x400330, + Size: 0x0, +@@ -136,8 +149,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x9, + Value: 0x400350, + Size: 0x0, +@@ -146,8 +159,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xA, + Value: 0x400368, + Size: 0x0, +@@ -156,8 +169,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xB, + Value: 0x400398, + Size: 0x0, +@@ -166,8 +179,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xC, + Value: 0x4003B0, + Size: 0x0, +@@ -176,8 +189,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xD, + Value: 0x4003E0, + Size: 0x0, +@@ -186,8 +199,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xE, + Value: 0x400594, + Size: 0x0, +@@ -196,8 +209,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xF, + Value: 0x4005A4, + Size: 0x0, +@@ -206,8 +219,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x10, + Value: 0x4005B8, + Size: 0x0, +@@ -216,8 +229,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x11, + Value: 0x4005E0, + Size: 0x0, +@@ -226,8 +239,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x12, + Value: 0x600688, + Size: 0x0, +@@ -236,8 +249,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x13, + Value: 0x600698, + Size: 0x0, +@@ -246,8 +259,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x14, + Value: 0x6006A8, + Size: 0x0, +@@ -256,8 +269,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x15, + Value: 0x6006B0, + Size: 0x0, +@@ -266,8 +279,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x16, + Value: 0x600850, + Size: 0x0, +@@ -276,8 +289,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x17, + Value: 0x600858, + Size: 0x0, +@@ -286,8 +299,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x18, + Value: 0x600880, + Size: 0x0, +@@ -296,8 +309,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x19, + Value: 0x600898, + Size: 0x0, +@@ -306,8 +319,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x1A, + Value: 0x0, + Size: 0x0, +@@ -316,8 +329,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x1B, + Value: 0x0, + Size: 0x0, +@@ -326,8 +339,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x1C, + Value: 0x0, + Size: 0x0, +@@ -336,8 +349,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x1D, + Value: 0x0, + Size: 0x0, +@@ -346,8 +359,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x1E, + Value: 0x0, + Size: 0x0, +@@ -356,8 +369,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x1F, + Value: 0x0, + Size: 0x0, +@@ -366,8 +379,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x20, + Value: 0x0, + Size: 0x0, +@@ -376,8 +389,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x21, + Value: 0x0, + Size: 0x0, +@@ -386,8 +399,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "init.c", + Info: 0x4, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, +@@ -396,8 +409,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "initfini.c", + Info: 0x4, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, +@@ -406,8 +419,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "call_gmon_start", + Info: 0x2, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xD, + Value: 0x40040C, + Size: 0x0, +@@ -416,8 +429,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "crtstuff.c", + Info: 0x4, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, +@@ -426,8 +439,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__CTOR_LIST__", + Info: 0x1, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x12, + Value: 0x600688, + Size: 0x0, +@@ -436,8 +449,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__DTOR_LIST__", + Info: 0x1, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x13, + Value: 0x600698, + Size: 0x0, +@@ -446,8 +459,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__JCR_LIST__", + Info: 0x1, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x14, + Value: 0x6006A8, + Size: 0x0, +@@ -456,8 +469,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__do_global_dtors_aux", + Info: 0x2, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xD, + Value: 0x400430, + Size: 0x0, +@@ -466,8 +479,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "completed.6183", + Info: 0x1, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x19, + Value: 0x600898, + Size: 0x1, +@@ -476,8 +489,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "p.6181", + Info: 0x1, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x18, + Value: 0x600890, + Size: 0x0, +@@ -486,8 +499,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "frame_dummy", + Info: 0x2, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xD, + Value: 0x400470, + Size: 0x0, +@@ -496,8 +509,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "crtstuff.c", + Info: 0x4, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, +@@ -506,8 +519,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__CTOR_END__", + Info: 0x1, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x12, + Value: 0x600690, + Size: 0x0, +@@ -516,8 +529,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__DTOR_END__", + Info: 0x1, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x13, + Value: 0x6006A0, + Size: 0x0, +@@ -526,8 +539,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__FRAME_END__", + Info: 0x1, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x11, + Value: 0x400680, + Size: 0x0, +@@ -536,8 +549,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__JCR_END__", + Info: 0x1, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x14, + Value: 0x6006A8, + Size: 0x0, +@@ -546,8 +559,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__do_global_ctors_aux", + Info: 0x2, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xD, + Value: 0x400560, + Size: 0x0, +@@ -556,8 +569,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "initfini.c", + Info: 0x4, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, +@@ -566,8 +579,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "hello.c", + Info: 0x4, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, +@@ -576,8 +589,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "_GLOBAL_OFFSET_TABLE_", + Info: 0x1, + Other: 0x2, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x17, + Value: 0x600858, + Size: 0x0, +@@ -586,8 +599,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__init_array_end", + Info: 0x0, + Other: 0x2, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x12, + Value: 0x600684, + Size: 0x0, +@@ -596,8 +609,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__init_array_start", + Info: 0x0, + Other: 0x2, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x12, + Value: 0x600684, + Size: 0x0, +@@ -606,8 +619,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "_DYNAMIC", + Info: 0x1, + Other: 0x2, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x15, + Value: 0x6006B0, + Size: 0x0, +@@ -616,8 +629,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "data_start", + Info: 0x20, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x18, + Value: 0x600880, + Size: 0x0, +@@ -626,8 +639,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__libc_csu_fini", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xD, + Value: 0x4004C0, + Size: 0x2, +@@ -636,8 +649,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "_start", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xD, + Value: 0x4003E0, + Size: 0x0, +@@ -646,8 +659,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__gmon_start__", + Info: 0x20, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x0, + Value: 0x0, + Size: 0x0, +@@ -656,8 +669,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "_Jv_RegisterClasses", + Info: 0x20, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x0, + Value: 0x0, + Size: 0x0, +@@ -666,8 +679,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "puts@@GLIBC_2.2.5", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x0, + Value: 0x0, + Size: 0x18C, +@@ -676,8 +689,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "_fini", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xE, + Value: 0x400594, + Size: 0x0, +@@ -686,8 +699,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__libc_start_main@@GLIBC_2.2.5", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x0, + Value: 0x0, + Size: 0x1C2, +@@ -696,8 +709,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "_IO_stdin_used", + Info: 0x11, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xF, + Value: 0x4005A4, + Size: 0x4, +@@ -706,8 +719,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__data_start", + Info: 0x10, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x18, + Value: 0x600880, + Size: 0x0, +@@ -716,8 +729,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__dso_handle", + Info: 0x11, + Other: 0x2, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x18, + Value: 0x600888, + Size: 0x0, +@@ -726,8 +739,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__libc_csu_init", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xD, + Value: 0x4004D0, + Size: 0x89, +@@ -736,8 +749,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "__bss_start", + Info: 0x10, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF1, + Value: 0x600898, + Size: 0x0, +@@ -746,8 +759,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "_end", + Info: 0x10, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF1, + Value: 0x6008A0, + Size: 0x0, +@@ -756,8 +769,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "_edata", + Info: 0x10, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF1, + Value: 0x600898, + Size: 0x0, +@@ -766,8 +779,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "main", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xD, + Value: 0x400498, + Size: 0x1B, +@@ -776,8 +789,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "_init", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xB, + Value: 0x400398, + Size: 0x0, +@@ -788,8 +801,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "go-relocation-test-clang.c", + Info: 0x4, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, +@@ -798,8 +811,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: ".Linfo_string0", + Info: 0x0, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xC, + Value: 0x0, + Size: 0x0, +@@ -808,8 +821,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: ".Linfo_string1", + Info: 0x0, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xC, + Value: 0x2C, + Size: 0x0, +@@ -818,8 +831,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: ".Linfo_string2", + Info: 0x0, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xC, + Value: 0x47, + Size: 0x0, +@@ -828,8 +841,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: ".Linfo_string3", + Info: 0x0, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xC, + Value: 0x4C, + Size: 0x0, +@@ -838,8 +851,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: ".Linfo_string4", + Info: 0x0, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xC, + Value: 0x4E, + Size: 0x0, +@@ -848,8 +861,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x1, + Value: 0x0, + Size: 0x0, +@@ -858,8 +871,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x2, + Value: 0x0, + Size: 0x0, +@@ -868,8 +881,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x3, + Value: 0x0, + Size: 0x0, +@@ -878,8 +891,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x4, + Value: 0x0, + Size: 0x0, +@@ -888,8 +901,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x6, + Value: 0x0, + Size: 0x0, +@@ -898,8 +911,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x7, + Value: 0x0, + Size: 0x0, +@@ -908,8 +921,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x8, + Value: 0x0, + Size: 0x0, +@@ -918,8 +931,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xA, + Value: 0x0, + Size: 0x0, +@@ -928,8 +941,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xC, + Value: 0x0, + Size: 0x0, +@@ -938,8 +951,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xD, + Value: 0x0, + Size: 0x0, +@@ -948,8 +961,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xE, + Value: 0x0, + Size: 0x0, +@@ -958,8 +971,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xF, + Value: 0x0, + Size: 0x0, +@@ -968,8 +981,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0x10, + Value: 0x0, + Size: 0x0, +@@ -978,8 +991,8 @@ var symbolsGolden = map[string][]Symbol{ + Name: "v", + Info: 0x11, + Other: 0x0, +- VersionScope: VersionScopeNone, +- VersionIndex: -1, ++ HasVersion: false, ++ VersionIndex: 0, + Section: 0xFFF2, + Value: 0x4, + Size: 0x4, +@@ -994,7 +1007,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "__gmon_start__", + Info: 0x20, + Other: 0x0, +- VersionScope: VersionScopeLocal, ++ HasVersion: true, + VersionIndex: 0x0, + Section: 0x0, + Value: 0x0, +@@ -1004,7 +1017,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "puts", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x2, + Section: 0x0, + Value: 0x0, +@@ -1016,7 +1029,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "__libc_start_main", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x2, + Section: 0x0, + Value: 0x0, +@@ -1032,7 +1045,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZNSo3putEc", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1044,7 +1057,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "strchr", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x4, + Section: 0x0, + Value: 0x0, +@@ -1056,7 +1069,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "__cxa_finalize", + Info: 0x22, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x4, + Section: 0x0, + Value: 0x0, +@@ -1068,7 +1081,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZNSo5tellpEv", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1080,7 +1093,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZNSo5seekpElSt12_Ios_Seekdir", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1092,7 +1105,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_Znwm", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1104,7 +1117,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZdlPvm", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x5, + Section: 0x0, + Value: 0x0, +@@ -1116,7 +1129,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "__stack_chk_fail", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x6, + Section: 0x0, + Value: 0x0, +@@ -1128,7 +1141,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x7, + Section: 0x0, + Value: 0x0, +@@ -1140,7 +1153,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZNSo5seekpESt4fposI11__mbstate_tE", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1152,7 +1165,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZNSi4readEPcl", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1164,7 +1177,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZNSi5seekgESt4fposI11__mbstate_tE", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1176,7 +1189,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZNSo5writeEPKcl", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1188,7 +1201,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZNSi5seekgElSt12_Ios_Seekdir", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1200,7 +1213,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZSt21ios_base_library_initv", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x8, + Section: 0x0, + Value: 0x0, +@@ -1212,7 +1225,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "TIFFClientOpen", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x9, + Section: 0x0, + Value: 0x0, +@@ -1224,7 +1237,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZNSt9basic_iosIcSt11char_traitsIcEE5clearESt12_Ios_Iostate", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1236,7 +1249,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ZNSi5tellgEv", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x3, + Section: 0x0, + Value: 0x0, +@@ -1248,7 +1261,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ITM_deregisterTMCloneTable", + Info: 0x20, + Other: 0x0, +- VersionScope: VersionScopeGlobal, ++ HasVersion: true, + VersionIndex: 0x1, + Section: 0x0, + Value: 0x0, +@@ -1258,7 +1271,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "__gmon_start__", + Info: 0x20, + Other: 0x0, +- VersionScope: VersionScopeGlobal, ++ HasVersion: true, + VersionIndex: 0x1, + Section: 0x0, + Value: 0x0, +@@ -1268,7 +1281,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_ITM_registerTMCloneTable", + Info: 0x20, + Other: 0x0, +- VersionScope: VersionScopeGlobal, ++ HasVersion: true, + VersionIndex: 0x1, + Section: 0x0, + Value: 0x0, +@@ -1278,7 +1291,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "LIBTIFFXX_4.0", + Info: 0x11, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x2, + Section: 0xFFF1, + Value: 0x0, +@@ -1290,7 +1303,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_Z14TIFFStreamOpenPKcPSo", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x2, + Section: 0xF, + Value: 0x1860, +@@ -1302,7 +1315,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ + Name: "_Z14TIFFStreamOpenPKcPSi", + Info: 0x12, + Other: 0x0, +- VersionScope: VersionScopeSpecific, ++ HasVersion: true, + VersionIndex: 0x2, + Section: 0xF, + Value: 0x1920, +diff --git a/src/encoding/binary/binary.go b/src/encoding/binary/binary.go +index d80aa8e11a..c92dfded27 100644 +--- a/src/encoding/binary/binary.go ++++ b/src/encoding/binary/binary.go +@@ -65,17 +65,20 @@ var BigEndian bigEndian + + type littleEndian struct{} + ++// Uint16 returns the uint16 representation of b[0:2]. + func (littleEndian) Uint16(b []byte) uint16 { + _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 + return uint16(b[0]) | uint16(b[1])<<8 + } + ++// PutUint16 stores v into b[0:2]. + func (littleEndian) PutUint16(b []byte, v uint16) { + _ = b[1] // early bounds check to guarantee safety of writes below + b[0] = byte(v) + b[1] = byte(v >> 8) + } + ++// AppendUint16 appends the bytes of v to b and returns the appended slice. + func (littleEndian) AppendUint16(b []byte, v uint16) []byte { + return append(b, + byte(v), +@@ -83,11 +86,13 @@ func (littleEndian) AppendUint16(b []byte, v uint16) []byte { + ) + } + ++// Uint32 returns the uint32 representation of b[0:4]. + func (littleEndian) Uint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + } + ++// PutUint32 stores v into b[0:4]. + func (littleEndian) PutUint32(b []byte, v uint32) { + _ = b[3] // early bounds check to guarantee safety of writes below + b[0] = byte(v) +@@ -96,6 +101,7 @@ func (littleEndian) PutUint32(b []byte, v uint32) { + b[3] = byte(v >> 24) + } + ++// AppendUint32 appends the bytes of v to b and returns the appended slice. + func (littleEndian) AppendUint32(b []byte, v uint32) []byte { + return append(b, + byte(v), +@@ -105,12 +111,14 @@ func (littleEndian) AppendUint32(b []byte, v uint32) []byte { + ) + } + ++// Uint64 returns the uint64 representation of b[0:8]. + func (littleEndian) Uint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + } + ++// PutUint64 stores v into b[0:8]. + func (littleEndian) PutUint64(b []byte, v uint64) { + _ = b[7] // early bounds check to guarantee safety of writes below + b[0] = byte(v) +@@ -123,6 +131,7 @@ func (littleEndian) PutUint64(b []byte, v uint64) { + b[7] = byte(v >> 56) + } + ++// AppendUint64 appends the bytes of v to b and returns the appended slice. + func (littleEndian) AppendUint64(b []byte, v uint64) []byte { + return append(b, + byte(v), +@@ -142,17 +151,20 @@ func (littleEndian) GoString() string { return "binary.LittleEndian" } + + type bigEndian struct{} + ++// Uint16 returns the uint16 representation of b[0:2]. + func (bigEndian) Uint16(b []byte) uint16 { + _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 + return uint16(b[1]) | uint16(b[0])<<8 + } + ++// PutUint16 stores v into b[0:2]. + func (bigEndian) PutUint16(b []byte, v uint16) { + _ = b[1] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 8) + b[1] = byte(v) + } + ++// AppendUint16 appends the bytes of v to b and returns the appended slice. + func (bigEndian) AppendUint16(b []byte, v uint16) []byte { + return append(b, + byte(v>>8), +@@ -160,11 +172,13 @@ func (bigEndian) AppendUint16(b []byte, v uint16) []byte { + ) + } + ++// Uint32 returns the uint32 representation of b[0:4]. + func (bigEndian) Uint32(b []byte) uint32 { + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 + } + ++// PutUint32 stores v into b[0:4]. + func (bigEndian) PutUint32(b []byte, v uint32) { + _ = b[3] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 24) +@@ -173,6 +187,7 @@ func (bigEndian) PutUint32(b []byte, v uint32) { + b[3] = byte(v) + } + ++// AppendUint32 appends the bytes of v to b and returns the appended slice. + func (bigEndian) AppendUint32(b []byte, v uint32) []byte { + return append(b, + byte(v>>24), +@@ -182,12 +197,14 @@ func (bigEndian) AppendUint32(b []byte, v uint32) []byte { + ) + } + ++// Uint64 returns the uint64 representation of b[0:8]. + func (bigEndian) Uint64(b []byte) uint64 { + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 + } + ++// PutUint64 stores v into b[0:8]. + func (bigEndian) PutUint64(b []byte, v uint64) { + _ = b[7] // early bounds check to guarantee safety of writes below + b[0] = byte(v >> 56) +@@ -200,6 +217,7 @@ func (bigEndian) PutUint64(b []byte, v uint64) { + b[7] = byte(v) + } + ++// AppendUint64 appends the bytes of v to b and returns the appended slice. + func (bigEndian) AppendUint64(b []byte, v uint64) []byte { + return append(b, + byte(v>>56), +diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go +index 98102291ab..3b398c9fc3 100644 +--- a/src/encoding/json/decode.go ++++ b/src/encoding/json/decode.go +@@ -113,9 +113,6 @@ func Unmarshal(data []byte, v any) error { + // The input can be assumed to be a valid encoding of + // a JSON value. UnmarshalJSON must copy the JSON data + // if it wishes to retain the data after returning. +-// +-// By convention, to approximate the behavior of [Unmarshal] itself, +-// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op. + type Unmarshaler interface { + UnmarshalJSON([]byte) error + } +diff --git a/src/encoding/json/decode_test.go b/src/encoding/json/decode_test.go +index de09fae50f..a2b462af77 100644 +--- a/src/encoding/json/decode_test.go ++++ b/src/encoding/json/decode_test.go +@@ -1797,19 +1797,12 @@ func TestNullString(t *testing.T) { + } + } + +-func intp(x int) *int { +- p := new(int) +- *p = x +- return p +-} +- +-func intpp(x *int) **int { +- pp := new(*int) +- *pp = x +- return pp ++func addr[T any](v T) *T { ++ return &v + } + + func TestInterfaceSet(t *testing.T) { ++ errUnmarshal := &UnmarshalTypeError{Value: "object", Offset: 6, Type: reflect.TypeFor[int](), Field: "X"} + tests := []struct { + CaseName + pre any +@@ -1820,21 +1813,55 @@ func TestInterfaceSet(t *testing.T) { + {Name(""), "foo", `2`, 2.0}, + {Name(""), "foo", `true`, true}, + {Name(""), "foo", `null`, nil}, +- +- {Name(""), nil, `null`, nil}, +- {Name(""), new(int), `null`, nil}, +- {Name(""), (*int)(nil), `null`, nil}, +- {Name(""), new(*int), `null`, new(*int)}, +- {Name(""), (**int)(nil), `null`, nil}, +- {Name(""), intp(1), `null`, nil}, +- {Name(""), intpp(nil), `null`, intpp(nil)}, +- {Name(""), intpp(intp(1)), `null`, intpp(nil)}, ++ {Name(""), map[string]any{}, `true`, true}, ++ {Name(""), []string{}, `true`, true}, ++ ++ {Name(""), any(nil), `null`, any(nil)}, ++ {Name(""), (*int)(nil), `null`, any(nil)}, ++ {Name(""), (*int)(addr(0)), `null`, any(nil)}, ++ {Name(""), (*int)(addr(1)), `null`, any(nil)}, ++ {Name(""), (**int)(nil), `null`, any(nil)}, ++ {Name(""), (**int)(addr[*int](nil)), `null`, (**int)(addr[*int](nil))}, ++ {Name(""), (**int)(addr(addr(1))), `null`, (**int)(addr[*int](nil))}, ++ {Name(""), (***int)(nil), `null`, any(nil)}, ++ {Name(""), (***int)(addr[**int](nil)), `null`, (***int)(addr[**int](nil))}, ++ {Name(""), (***int)(addr(addr[*int](nil))), `null`, (***int)(addr[**int](nil))}, ++ {Name(""), (***int)(addr(addr(addr(1)))), `null`, (***int)(addr[**int](nil))}, ++ ++ {Name(""), any(nil), `2`, float64(2)}, ++ {Name(""), (int)(1), `2`, float64(2)}, ++ {Name(""), (*int)(nil), `2`, float64(2)}, ++ {Name(""), (*int)(addr(0)), `2`, (*int)(addr(2))}, ++ {Name(""), (*int)(addr(1)), `2`, (*int)(addr(2))}, ++ {Name(""), (**int)(nil), `2`, float64(2)}, ++ {Name(""), (**int)(addr[*int](nil)), `2`, (**int)(addr(addr(2)))}, ++ {Name(""), (**int)(addr(addr(1))), `2`, (**int)(addr(addr(2)))}, ++ {Name(""), (***int)(nil), `2`, float64(2)}, ++ {Name(""), (***int)(addr[**int](nil)), `2`, (***int)(addr(addr(addr(2))))}, ++ {Name(""), (***int)(addr(addr[*int](nil))), `2`, (***int)(addr(addr(addr(2))))}, ++ {Name(""), (***int)(addr(addr(addr(1)))), `2`, (***int)(addr(addr(addr(2))))}, ++ ++ {Name(""), any(nil), `{}`, map[string]any{}}, ++ {Name(""), (int)(1), `{}`, map[string]any{}}, ++ {Name(""), (*int)(nil), `{}`, map[string]any{}}, ++ {Name(""), (*int)(addr(0)), `{}`, errUnmarshal}, ++ {Name(""), (*int)(addr(1)), `{}`, errUnmarshal}, ++ {Name(""), (**int)(nil), `{}`, map[string]any{}}, ++ {Name(""), (**int)(addr[*int](nil)), `{}`, errUnmarshal}, ++ {Name(""), (**int)(addr(addr(1))), `{}`, errUnmarshal}, ++ {Name(""), (***int)(nil), `{}`, map[string]any{}}, ++ {Name(""), (***int)(addr[**int](nil)), `{}`, errUnmarshal}, ++ {Name(""), (***int)(addr(addr[*int](nil))), `{}`, errUnmarshal}, ++ {Name(""), (***int)(addr(addr(addr(1)))), `{}`, errUnmarshal}, + } + for _, tt := range tests { + t.Run(tt.Name, func(t *testing.T) { + b := struct{ X any }{tt.pre} + blob := `{"X":` + tt.json + `}` + if err := Unmarshal([]byte(blob), &b); err != nil { ++ if wantErr, _ := tt.post.(error); equalError(err, wantErr) { ++ return ++ } + t.Fatalf("%s: Unmarshal(%#q) error: %v", tt.Where, blob, err) + } + if !reflect.DeepEqual(b.X, tt.post) { +diff --git a/src/fmt/doc.go b/src/fmt/doc.go +index b90db7bedc..fa0ffa7f00 100644 +--- a/src/fmt/doc.go ++++ b/src/fmt/doc.go +@@ -50,6 +50,9 @@ Floating-point and complex constituents: + %x hexadecimal notation (with decimal power of two exponent), e.g. -0x1.23abcp+20 + %X upper-case hexadecimal notation, e.g. -0X1.23ABCP+20 + ++ The exponent is always a decimal integer. ++ For formats other than %b the exponent is at least two digits. ++ + String and slice of bytes (treated equivalently with these verbs): + + %s the uninterpreted bytes of the string or slice +diff --git a/src/fmt/fmt_test.go b/src/fmt/fmt_test.go +index b7f9ccd494..82daf62771 100644 +--- a/src/fmt/fmt_test.go ++++ b/src/fmt/fmt_test.go +@@ -11,7 +11,6 @@ import ( + "io" + "math" + "reflect" +- "runtime" + "strings" + "testing" + "time" +@@ -112,6 +111,19 @@ func (p *P) String() string { + return "String(p)" + } + ++// Fn is a function type with a String method. ++type Fn func() int ++ ++func (fn Fn) String() string { return "String(fn)" } ++ ++var fnValue Fn ++ ++// U is a type with two unexported function fields. ++type U struct { ++ u func() string ++ fn Fn ++} ++ + var barray = [5]renamedUint8{1, 2, 3, 4, 5} + var bslice = barray[:] + +@@ -714,7 +726,6 @@ var fmtTests = []struct { + // go syntax + {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`}, + {"%#v", new(byte), "(*uint8)(0xPTR)"}, +- {"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"}, + {"%#v", make(chan int), "(chan int)(0xPTR)"}, + {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"}, + {"%#v", 1000000000, "1000000000"}, +@@ -737,6 +748,54 @@ var fmtTests = []struct { + {"%#v", 1.2345678, "1.2345678"}, + {"%#v", float32(1.2345678), "1.2345678"}, + ++ // functions ++ {"%v", TestFmtInterface, "0xPTR"}, // simple function ++ {"%v", reflect.ValueOf(TestFmtInterface), "0xPTR"}, ++ {"%v", G.GoString, "0xPTR"}, // method expression ++ {"%v", reflect.ValueOf(G.GoString), "0xPTR"}, ++ {"%v", G(23).GoString, "0xPTR"}, // method value ++ {"%v", reflect.ValueOf(G(23).GoString), "0xPTR"}, ++ {"%v", reflect.ValueOf(G(23)).Method(0), "0xPTR"}, ++ {"%v", Fn.String, "0xPTR"}, // method of function type ++ {"%v", reflect.ValueOf(Fn.String), "0xPTR"}, ++ {"%v", fnValue, "String(fn)"}, // variable of function type with String method ++ {"%v", reflect.ValueOf(fnValue), "String(fn)"}, ++ {"%v", [1]Fn{fnValue}, "[String(fn)]"}, // array of function type with String method ++ {"%v", reflect.ValueOf([1]Fn{fnValue}), "[String(fn)]"}, ++ {"%v", fnValue.String, "0xPTR"}, // method value from function type ++ {"%v", reflect.ValueOf(fnValue.String), "0xPTR"}, ++ {"%v", reflect.ValueOf(fnValue).Method(0), "0xPTR"}, ++ {"%v", U{}.u, " "}, // unexported function field ++ {"%v", reflect.ValueOf(U{}.u), " "}, ++ {"%v", reflect.ValueOf(U{}).Field(0), " "}, ++ {"%v", U{fn: fnValue}.fn, "String(fn)"}, // unexported field of function type with String method ++ {"%v", reflect.ValueOf(U{fn: fnValue}.fn), "String(fn)"}, ++ {"%v", reflect.ValueOf(U{fn: fnValue}).Field(1), " "}, ++ ++ // functions with go syntax ++ {"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"}, // simple function ++ {"%#v", reflect.ValueOf(TestFmtInterface), "(func(*testing.T))(0xPTR)"}, ++ {"%#v", G.GoString, "(func(fmt_test.G) string)(0xPTR)"}, // method expression ++ {"%#v", reflect.ValueOf(G.GoString), "(func(fmt_test.G) string)(0xPTR)"}, ++ {"%#v", G(23).GoString, "(func() string)(0xPTR)"}, // method value ++ {"%#v", reflect.ValueOf(G(23).GoString), "(func() string)(0xPTR)"}, ++ {"%#v", reflect.ValueOf(G(23)).Method(0), "(func() string)(0xPTR)"}, ++ {"%#v", Fn.String, "(func(fmt_test.Fn) string)(0xPTR)"}, // method of function type ++ {"%#v", reflect.ValueOf(Fn.String), "(func(fmt_test.Fn) string)(0xPTR)"}, ++ {"%#v", fnValue, "(fmt_test.Fn)(nil)"}, // variable of function type with String method ++ {"%#v", reflect.ValueOf(fnValue), "(fmt_test.Fn)(nil)"}, ++ {"%#v", [1]Fn{fnValue}, "[1]fmt_test.Fn{(fmt_test.Fn)(nil)}"}, // array of function type with String method ++ {"%#v", reflect.ValueOf([1]Fn{fnValue}), "[1]fmt_test.Fn{(fmt_test.Fn)(nil)}"}, ++ {"%#v", fnValue.String, "(func() string)(0xPTR)"}, // method value from function type ++ {"%#v", reflect.ValueOf(fnValue.String), "(func() string)(0xPTR)"}, ++ {"%#v", reflect.ValueOf(fnValue).Method(0), "(func() string)(0xPTR)"}, ++ {"%#v", U{}.u, "(func() string)(nil)"}, // unexported function field ++ {"%#v", reflect.ValueOf(U{}.u), "(func() string)(nil)"}, ++ {"%#v", reflect.ValueOf(U{}).Field(0), "(func() string)(nil)"}, ++ {"%#v", U{fn: fnValue}.fn, "(fmt_test.Fn)(nil)"}, // unexported field of function type with String method ++ {"%#v", reflect.ValueOf(U{fn: fnValue}.fn), "(fmt_test.Fn)(nil)"}, ++ {"%#v", reflect.ValueOf(U{fn: fnValue}).Field(1), "(fmt_test.Fn)(nil)"}, ++ + // Whole number floats are printed without decimals. See Issue 27634. + {"%#v", 1.0, "1"}, + {"%#v", 1000000.0, "1e+06"}, +@@ -1438,6 +1497,9 @@ var mallocTest = []struct { + {0, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }}, + {0, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x", 7) }}, + {0, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x", 1<<16) }}, ++ {1, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); i := 1 << 16; Fprintf(&mallocBuf, "%x", i) }}, // not constant ++ {4, `Fprintf(buf, "%v")`, func() { mallocBuf.Reset(); s := []int{1, 2}; Fprintf(&mallocBuf, "%v", s) }}, ++ {1, `Fprintf(buf, "%v")`, func() { mallocBuf.Reset(); type P struct{ x, y int }; Fprintf(&mallocBuf, "%v", P{1, 2}) }}, + {2, `Fprintf(buf, "%80000s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%80000s", "hello") }}, // large buffer (>64KB) + // If the interface value doesn't need to allocate, amortized allocation overhead should be zero. + {0, `Fprintf(buf, "%x %x %x")`, func() { +@@ -1452,8 +1514,6 @@ func TestCountMallocs(t *testing.T) { + switch { + case testing.Short(): + t.Skip("skipping malloc count in short mode") +- case runtime.GOMAXPROCS(0) > 1: +- t.Skip("skipping; GOMAXPROCS>1") + case race.Enabled: + t.Skip("skipping malloc count under race detector") + } +diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go +index cc7f4df7f3..a62a5173b9 100644 +--- a/src/go/build/deps_test.go ++++ b/src/go/build/deps_test.go +@@ -444,6 +444,10 @@ var depsRules = ` + NET, log + < net/mail; + ++ # FIPS is the FIPS 140 module. ++ # It must not depend on external crypto packages. ++ # See also fips140deps.AllowedInternalPackages. ++ + io, math/rand/v2 < crypto/internal/randutil; + + STR < crypto/internal/impl; +@@ -455,8 +459,6 @@ var depsRules = ` + internal/cpu, internal/goarch < crypto/internal/fips140deps/cpu; + internal/godebug < crypto/internal/fips140deps/godebug; + +- # FIPS is the FIPS 140 module. +- # It must not depend on external crypto packages. + STR, crypto/internal/impl, + crypto/internal/entropy, + crypto/internal/randutil, +@@ -491,63 +493,49 @@ var depsRules = ` + < crypto/internal/fips140/rsa + < FIPS; + +- FIPS < crypto/internal/fips140/check/checktest; ++ FIPS, internal/godebug < crypto/fips140; + +- FIPS, sync/atomic < crypto/tls/internal/fips140tls; ++ crypto, hash !< FIPS; + +- FIPS, internal/godebug, hash < crypto/fips140, crypto/internal/fips140only; ++ # CRYPTO is core crypto algorithms - no cgo, fmt, net. ++ # Mostly wrappers around the FIPS module. + + NONE < crypto/internal/boring/sig, crypto/internal/boring/syso; +- sync/atomic < crypto/internal/boring/bcache, crypto/internal/boring/fips140tls; +- crypto/internal/boring/sig, crypto/tls/internal/fips140tls < crypto/tls/fipsonly; ++ sync/atomic < crypto/internal/boring/bcache; + +- # CRYPTO is core crypto algorithms - no cgo, fmt, net. +- FIPS, crypto/internal/fips140only, ++ FIPS, internal/godebug, hash, embed, + crypto/internal/boring/sig, + crypto/internal/boring/syso, +- golang.org/x/sys/cpu, +- hash, embed ++ crypto/internal/boring/bcache ++ < crypto/internal/fips140only + < crypto + < crypto/subtle + < crypto/cipher +- < crypto/sha3; +- +- crypto/cipher, +- crypto/internal/boring/bcache + < crypto/internal/boring +- < crypto/boring; +- +- crypto/boring +- < crypto/aes, crypto/des, crypto/hmac, crypto/md5, crypto/rc4, +- crypto/sha1, crypto/sha256, crypto/sha512, crypto/hkdf; +- +- crypto/boring, crypto/internal/fips140/edwards25519/field +- < crypto/ecdh; +- +- crypto/hmac < crypto/pbkdf2; +- +- crypto/internal/fips140/mlkem < crypto/mlkem; +- +- crypto/aes, +- crypto/des, +- crypto/ecdh, +- crypto/hmac, +- crypto/md5, +- crypto/rc4, +- crypto/sha1, +- crypto/sha256, +- crypto/sha512, +- crypto/sha3, +- crypto/hkdf ++ < crypto/boring ++ < crypto/aes, ++ crypto/des, ++ crypto/rc4, ++ crypto/md5, ++ crypto/sha1, ++ crypto/sha256, ++ crypto/sha512, ++ crypto/sha3, ++ crypto/hmac, ++ crypto/hkdf, ++ crypto/pbkdf2, ++ crypto/ecdh, ++ crypto/mlkem + < CRYPTO; + + CGO, fmt, net !< CRYPTO; + +- # CRYPTO-MATH is core bignum-based crypto - no cgo, net; fmt now ok. ++ # CRYPTO-MATH is crypto that exposes math/big APIs - no cgo, net; fmt now ok. ++ + CRYPTO, FMT, math/big + < crypto/internal/boring/bbig + < crypto/rand +- < crypto/ed25519 ++ < crypto/ed25519 # depends on crypto/rand.Reader + < encoding/asn1 + < golang.org/x/crypto/cryptobyte/asn1 + < golang.org/x/crypto/cryptobyte +@@ -558,23 +546,29 @@ var depsRules = ` + CGO, net !< CRYPTO-MATH; + + # TLS, Prince of Dependencies. +- CRYPTO-MATH, NET, container/list, encoding/hex, encoding/pem ++ ++ FIPS, sync/atomic < crypto/tls/internal/fips140tls; ++ ++ crypto/internal/boring/sig, crypto/tls/internal/fips140tls < crypto/tls/fipsonly; ++ ++ CRYPTO, golang.org/x/sys/cpu, encoding/binary, reflect + < golang.org/x/crypto/internal/alias + < golang.org/x/crypto/internal/subtle + < golang.org/x/crypto/chacha20 + < golang.org/x/crypto/internal/poly1305 +- < golang.org/x/crypto/chacha20poly1305 ++ < golang.org/x/crypto/chacha20poly1305; ++ ++ CRYPTO-MATH, NET, container/list, encoding/hex, encoding/pem, ++ golang.org/x/crypto/chacha20poly1305, crypto/tls/internal/fips140tls + < crypto/internal/hpke + < crypto/x509/internal/macos +- < crypto/x509/pkix; +- +- crypto/tls/internal/fips140tls, crypto/x509/pkix ++ < crypto/x509/pkix + < crypto/x509 + < crypto/tls; + + # crypto-aware packages + +- DEBUG, go/build, go/types, text/scanner, crypto/md5 ++ DEBUG, go/build, go/types, text/scanner, crypto/sha256 + < internal/pkgbits, internal/exportdata + < go/internal/gcimporter, go/internal/gccgoimporter, go/internal/srcimporter + < go/importer; +@@ -666,7 +660,7 @@ var depsRules = ` + < testing/slogtest; + + FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, +- internal/godebug, math/rand, encoding/hex, crypto/sha256 ++ internal/godebug, math/rand, encoding/hex + < internal/fuzz; + + OS, flag, testing, internal/cfg, internal/platform, internal/goroot +@@ -696,6 +690,9 @@ var depsRules = ` + CGO, FMT + < crypto/internal/sysrand/internal/seccomp; + ++ FIPS ++ < crypto/internal/fips140/check/checktest; ++ + # v2 execution trace parser. + FMT + < internal/trace/event; +diff --git a/src/go/doc/example.go b/src/go/doc/example.go +index 0618f2bd9b..7a8c26291d 100644 +--- a/src/go/doc/example.go ++++ b/src/go/doc/example.go +@@ -192,13 +192,6 @@ func playExample(file *ast.File, f *ast.FuncDecl) *ast.File { + // Find unresolved identifiers and uses of top-level declarations. + depDecls, unresolved := findDeclsAndUnresolved(body, topDecls, typMethods) + +- // Remove predeclared identifiers from unresolved list. +- for n := range unresolved { +- if predeclaredTypes[n] || predeclaredConstants[n] || predeclaredFuncs[n] { +- delete(unresolved, n) +- } +- } +- + // Use unresolved identifiers to determine the imports used by this + // example. The heuristic assumes package names match base import + // paths for imports w/o renames (should be good enough most of the time). +@@ -251,6 +244,13 @@ func playExample(file *ast.File, f *ast.FuncDecl) *ast.File { + } + } + ++ // Remove predeclared identifiers from unresolved list. ++ for n := range unresolved { ++ if predeclaredTypes[n] || predeclaredConstants[n] || predeclaredFuncs[n] { ++ delete(unresolved, n) ++ } ++ } ++ + // If there are other unresolved identifiers, give up because this + // synthesized file is not going to build. + if len(unresolved) > 0 { +diff --git a/src/go/doc/testdata/examples/shadow_predeclared.go b/src/go/doc/testdata/examples/shadow_predeclared.go +new file mode 100644 +index 0000000000..7e9f30d9b4 +--- /dev/null ++++ b/src/go/doc/testdata/examples/shadow_predeclared.go +@@ -0,0 +1,19 @@ ++// Copyright 2021 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package foo_test ++ ++import ( ++ "fmt" ++ ++ "example.com/error" ++) ++ ++func Print(s string) { ++ fmt.Println(s) ++} ++ ++func Example() { ++ Print(error.Hello) ++} +diff --git a/src/go/doc/testdata/examples/shadow_predeclared.golden b/src/go/doc/testdata/examples/shadow_predeclared.golden +new file mode 100644 +index 0000000000..65598bed62 +--- /dev/null ++++ b/src/go/doc/testdata/examples/shadow_predeclared.golden +@@ -0,0 +1,16 @@ ++-- .Play -- ++package main ++ ++import ( ++ "fmt" ++ ++ "example.com/error" ++) ++ ++func Print(s string) { ++ fmt.Println(s) ++} ++ ++func main() { ++ Print(error.Hello) ++} +diff --git a/src/go/types/api.go b/src/go/types/api.go +index dea974bec8..beb2258c8b 100644 +--- a/src/go/types/api.go ++++ b/src/go/types/api.go +@@ -217,11 +217,19 @@ type Info struct { + // + // The Types map does not record the type of every identifier, + // only those that appear where an arbitrary expression is +- // permitted. For instance, the identifier f in a selector +- // expression x.f is found only in the Selections map, the +- // identifier z in a variable declaration 'var z int' is found +- // only in the Defs map, and identifiers denoting packages in +- // qualified identifiers are collected in the Uses map. ++ // permitted. For instance: ++ // - an identifier f in a selector expression x.f is found ++ // only in the Selections map; ++ // - an identifier z in a variable declaration 'var z int' ++ // is found only in the Defs map; ++ // - an identifier p denoting a package in a qualified ++ // identifier p.X is found only in the Uses map. ++ // ++ // Similarly, no type is recorded for the (synthetic) FuncType ++ // node in a FuncDecl.Type field, since there is no corresponding ++ // syntactic function type expression in the source in this case ++ // Instead, the function type is found in the Defs.map entry for ++ // the corresponding function declaration. + Types map[ast.Expr]TypeAndValue + + // Instances maps identifiers denoting generic types or functions to their +diff --git a/src/go/types/signature.go b/src/go/types/signature.go +index 681eb85fd7..ff405318ee 100644 +--- a/src/go/types/signature.go ++++ b/src/go/types/signature.go +@@ -195,7 +195,7 @@ func (check *Checker) collectRecv(rparam *ast.Field, scopePos token.Pos) (*Var, + } else { + // If there are type parameters, rbase must denote a generic base type. + // Important: rbase must be resolved before declaring any receiver type +- // parameters (wich may have the same name, see below). ++ // parameters (which may have the same name, see below). + var baseType *Named // nil if not valid + var cause string + if t := check.genericType(rbase, &cause); isValid(t) { +diff --git a/src/internal/exportdata/exportdata.go b/src/internal/exportdata/exportdata.go +index 27675923b5..861a47f49f 100644 +--- a/src/internal/exportdata/exportdata.go ++++ b/src/internal/exportdata/exportdata.go +@@ -85,6 +85,7 @@ func ReadUnified(r *bufio.Reader) (data []byte, err error) { + + if n < 0 { + err = fmt.Errorf("invalid size (%d) in the archive file: %d bytes remain without section headers (recompile package)", size, n) ++ return + } + + // Read n bytes from buf. +diff --git a/src/internal/fuzz/mutators_byteslice_test.go b/src/internal/fuzz/mutators_byteslice_test.go +index 56adca2537..b12ef6cbcd 100644 +--- a/src/internal/fuzz/mutators_byteslice_test.go ++++ b/src/internal/fuzz/mutators_byteslice_test.go +@@ -34,12 +34,6 @@ func (mr *mockRand) uint32n(n uint32) uint32 { + return uint32(c) % n + } + +-func (mr *mockRand) exp2() int { +- c := mr.values[mr.counter] +- mr.counter++ +- return c +-} +- + func (mr *mockRand) bool() bool { + b := mr.b + mr.b = !mr.b +diff --git a/src/internal/fuzz/pcg.go b/src/internal/fuzz/pcg.go +index dc07b9f5bd..b8251043f1 100644 +--- a/src/internal/fuzz/pcg.go ++++ b/src/internal/fuzz/pcg.go +@@ -17,7 +17,6 @@ type mutatorRand interface { + uint32() uint32 + intn(int) int + uint32n(uint32) uint32 +- exp2() int + bool() bool + + save(randState, randInc *uint64) +@@ -123,11 +122,6 @@ func (r *pcgRand) uint32n(n uint32) uint32 { + return uint32(prod >> 32) + } + +-// exp2 generates n with probability 1/2^(n+1). +-func (r *pcgRand) exp2() int { +- return bits.TrailingZeros32(r.uint32()) +-} +- + // bool generates a random bool. + func (r *pcgRand) bool() bool { + return r.uint32()&1 == 0 +diff --git a/src/internal/goexperiment/exp_synctest_off.go b/src/internal/goexperiment/exp_synctest_off.go +new file mode 100644 +index 0000000000..fade13f89c +--- /dev/null ++++ b/src/internal/goexperiment/exp_synctest_off.go +@@ -0,0 +1,8 @@ ++// Code generated by mkconsts.go. DO NOT EDIT. ++ ++//go:build !goexperiment.synctest ++ ++package goexperiment ++ ++const Synctest = false ++const SynctestInt = 0 +diff --git a/src/internal/goexperiment/exp_synctest_on.go b/src/internal/goexperiment/exp_synctest_on.go +new file mode 100644 +index 0000000000..9c44be7276 +--- /dev/null ++++ b/src/internal/goexperiment/exp_synctest_on.go +@@ -0,0 +1,8 @@ ++// Code generated by mkconsts.go. DO NOT EDIT. ++ ++//go:build goexperiment.synctest ++ ++package goexperiment ++ ++const Synctest = true ++const SynctestInt = 1 +diff --git a/src/internal/pkgbits/encoder.go b/src/internal/pkgbits/encoder.go +index c17a12399d..015842f58c 100644 +--- a/src/internal/pkgbits/encoder.go ++++ b/src/internal/pkgbits/encoder.go +@@ -6,7 +6,7 @@ package pkgbits + + import ( + "bytes" +- "crypto/md5" ++ "crypto/sha256" + "encoding/binary" + "go/constant" + "io" +@@ -55,7 +55,7 @@ func NewPkgEncoder(version Version, syncFrames int) PkgEncoder { + // DumpTo writes the package's encoded data to out0 and returns the + // package fingerprint. + func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) { +- h := md5.New() ++ h := sha256.New() + out := io.MultiWriter(out0, h) + + writeUint32 := func(x uint32) { +diff --git a/src/internal/runtime/maps/map.go b/src/internal/runtime/maps/map.go +index ffafcacdea..62463351c7 100644 +--- a/src/internal/runtime/maps/map.go ++++ b/src/internal/runtime/maps/map.go +@@ -194,6 +194,7 @@ func h2(h uintptr) uintptr { + type Map struct { + // The number of filled slots (i.e. the number of elements in all + // tables). Excludes deleted slots. ++ // Must be first (known by the compiler, for len() builtin). + used uint64 + + // seed is the hash seed, computed as a unique random number per map. +diff --git a/src/internal/sync/hashtriemap.go b/src/internal/sync/hashtriemap.go +index d31d81df39..6f5e0b437f 100644 +--- a/src/internal/sync/hashtriemap.go ++++ b/src/internal/sync/hashtriemap.go +@@ -79,7 +79,7 @@ func (ht *HashTrieMap[K, V]) Load(key K) (value V, ok bool) { + } + i = n.indirect() + } +- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") ++ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") + } + + // LoadOrStore returns the existing value for the key if present. +@@ -120,7 +120,7 @@ func (ht *HashTrieMap[K, V]) LoadOrStore(key K, value V) (result V, loaded bool) + i = n.indirect() + } + if !haveInsertPoint { +- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") ++ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") + } + + // Grab the lock and double-check what we saw. +@@ -178,7 +178,7 @@ func (ht *HashTrieMap[K, V]) expand(oldEntry, newEntry *entry[K, V], newHash uin + top := newIndirect + for { + if hashShift == 0 { +- panic("internal/concurrent.HashMapTrie: ran out of hash bits while inserting") ++ panic("internal/sync.HashTrieMap: ran out of hash bits while inserting") + } + hashShift -= nChildrenLog2 // hashShift is for the level parent is at. We need to go deeper. + oi := (oldHash >> hashShift) & nChildrenMask +@@ -219,26 +219,16 @@ func (ht *HashTrieMap[K, V]) Swap(key K, new V) (previous V, loaded bool) { + + slot = &i.children[(hash>>hashShift)&nChildrenMask] + n = slot.Load() +- if n == nil { ++ if n == nil || n.isEntry { + // We found a nil slot which is a candidate for insertion, + // or an existing entry that we'll replace. + haveInsertPoint = true + break + } +- if n.isEntry { +- // Swap if the keys compare. +- old, swapped := n.entry().swap(key, new) +- if swapped { +- return old, true +- } +- // If we fail, that means we should try to insert. +- haveInsertPoint = true +- break +- } + i = n.indirect() + } + if !haveInsertPoint { +- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") ++ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") + } + + // Grab the lock and double-check what we saw. +@@ -261,10 +251,11 @@ func (ht *HashTrieMap[K, V]) Swap(key K, new V) (previous V, loaded bool) { + var zero V + var oldEntry *entry[K, V] + if n != nil { +- // Between before and now, something got inserted. Swap if the keys compare. ++ // Swap if the keys compare. + oldEntry = n.entry() +- old, swapped := oldEntry.swap(key, new) ++ newEntry, old, swapped := oldEntry.swap(key, new) + if swapped { ++ slot.Store(&newEntry.node) + return old, true + } + } +@@ -292,30 +283,25 @@ func (ht *HashTrieMap[K, V]) CompareAndSwap(key K, old, new V) (swapped bool) { + panic("called CompareAndSwap when value is not of comparable type") + } + hash := ht.keyHash(abi.NoEscape(unsafe.Pointer(&key)), ht.seed) +- for { +- // Find the key or return if it's not there. +- i := ht.root.Load() +- hashShift := 8 * goarch.PtrSize +- found := false +- for hashShift != 0 { +- hashShift -= nChildrenLog2 + +- slot := &i.children[(hash>>hashShift)&nChildrenMask] +- n := slot.Load() +- if n == nil { +- // Nothing to compare with. Give up. +- return false +- } +- if n.isEntry { +- // We found an entry. Try to compare and swap directly. +- return n.entry().compareAndSwap(key, old, new, ht.valEqual) +- } +- i = n.indirect() +- } +- if !found { +- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") +- } ++ // Find a node with the key and compare with it. n != nil if we found the node. ++ i, _, slot, n := ht.find(key, hash, ht.valEqual, old) ++ if i != nil { ++ defer i.mu.Unlock() ++ } ++ if n == nil { ++ return false ++ } ++ ++ // Try to swap the entry. ++ e, swapped := n.entry().compareAndSwap(key, old, new, ht.valEqual) ++ if !swapped { ++ // Nothing was actually swapped, which means the node is no longer there. ++ return false + } ++ // Store the entry back because it changed. ++ slot.Store(&e.node) ++ return true + } + + // LoadAndDelete deletes the value for a key, returning the previous value if any. +@@ -353,7 +339,7 @@ func (ht *HashTrieMap[K, V]) LoadAndDelete(key K) (value V, loaded bool) { + // Check if the node is now empty (and isn't the root), and delete it if able. + for i.parent != nil && i.empty() { + if hashShift == 8*goarch.PtrSize { +- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") ++ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") + } + hashShift += nChildrenLog2 + +@@ -415,7 +401,7 @@ func (ht *HashTrieMap[K, V]) CompareAndDelete(key K, old V) (deleted bool) { + // Check if the node is now empty (and isn't the root), and delete it if able. + for i.parent != nil && i.empty() { + if hashShift == 8*goarch.PtrSize { +- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") ++ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") + } + hashShift += nChildrenLog2 + +@@ -468,7 +454,7 @@ func (ht *HashTrieMap[K, V]) find(key K, hash uintptr, valEqual equalFunc, value + i = n.indirect() + } + if !found { +- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") ++ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") + } + + // Grab the lock and double-check what we saw. +@@ -523,7 +509,7 @@ func (ht *HashTrieMap[K, V]) iter(i *indirect[K, V], yield func(key K, value V) + } + e := n.entry() + for e != nil { +- if !yield(e.key, *e.value.Load()) { ++ if !yield(e.key, e.value) { + return false + } + e = e.overflow.Load() +@@ -579,22 +565,21 @@ type entry[K comparable, V any] struct { + node[K, V] + overflow atomic.Pointer[entry[K, V]] // Overflow for hash collisions. + key K +- value atomic.Pointer[V] ++ value V + } + + func newEntryNode[K comparable, V any](key K, value V) *entry[K, V] { +- e := &entry[K, V]{ +- node: node[K, V]{isEntry: true}, +- key: key, ++ return &entry[K, V]{ ++ node: node[K, V]{isEntry: true}, ++ key: key, ++ value: value, + } +- e.value.Store(&value) +- return e + } + + func (e *entry[K, V]) lookup(key K) (V, bool) { + for e != nil { + if e.key == key { +- return *e.value.Load(), true ++ return e.value, true + } + e = e.overflow.Load() + } +@@ -603,87 +588,69 @@ func (e *entry[K, V]) lookup(key K) (V, bool) { + + func (e *entry[K, V]) lookupWithValue(key K, value V, valEqual equalFunc) (V, bool) { + for e != nil { +- oldp := e.value.Load() +- if e.key == key && (valEqual == nil || valEqual(unsafe.Pointer(oldp), abi.NoEscape(unsafe.Pointer(&value)))) { +- return *oldp, true ++ if e.key == key && (valEqual == nil || valEqual(unsafe.Pointer(&e.value), abi.NoEscape(unsafe.Pointer(&value)))) { ++ return e.value, true + } + e = e.overflow.Load() + } + return *new(V), false + } + +-// swap replaces a value in the overflow chain if keys compare equal. +-// Returns the old value, and whether or not anything was swapped. ++// swap replaces an entry in the overflow chain if keys compare equal. Returns the new entry chain, ++// the old value, and whether or not anything was swapped. + // + // swap must be called under the mutex of the indirect node which e is a child of. +-func (head *entry[K, V]) swap(key K, newv V) (V, bool) { ++func (head *entry[K, V]) swap(key K, new V) (*entry[K, V], V, bool) { + if head.key == key { +- vp := new(V) +- *vp = newv +- oldp := head.value.Swap(vp) +- return *oldp, true ++ // Return the new head of the list. ++ e := newEntryNode(key, new) ++ if chain := head.overflow.Load(); chain != nil { ++ e.overflow.Store(chain) ++ } ++ return e, head.value, true + } + i := &head.overflow + e := i.Load() + for e != nil { + if e.key == key { +- vp := new(V) +- *vp = newv +- oldp := e.value.Swap(vp) +- return *oldp, true ++ eNew := newEntryNode(key, new) ++ eNew.overflow.Store(e.overflow.Load()) ++ i.Store(eNew) ++ return head, e.value, true + } + i = &e.overflow + e = e.overflow.Load() + } + var zero V +- return zero, false ++ return head, zero, false + } + +-// compareAndSwap replaces a value for a matching key and existing value in the overflow chain. +-// Returns whether or not anything was swapped. ++// compareAndSwap replaces an entry in the overflow chain if both the key and value compare ++// equal. Returns the new entry chain and whether or not anything was swapped. + // + // compareAndSwap must be called under the mutex of the indirect node which e is a child of. +-func (head *entry[K, V]) compareAndSwap(key K, oldv, newv V, valEqual equalFunc) bool { +- var vbox *V +-outerLoop: +- for { +- oldvp := head.value.Load() +- if head.key == key && valEqual(unsafe.Pointer(oldvp), abi.NoEscape(unsafe.Pointer(&oldv))) { +- // Return the new head of the list. +- if vbox == nil { +- // Delay explicit creation of a new value to hold newv. If we just pass &newv +- // to CompareAndSwap, then newv will unconditionally escape, even if the CAS fails. +- vbox = new(V) +- *vbox = newv +- } +- if head.value.CompareAndSwap(oldvp, vbox) { +- return true +- } +- // We need to restart from the head of the overflow list in case, due to a removal, a node +- // is moved up the list and we miss it. +- continue outerLoop ++func (head *entry[K, V]) compareAndSwap(key K, old, new V, valEqual equalFunc) (*entry[K, V], bool) { ++ if head.key == key && valEqual(unsafe.Pointer(&head.value), abi.NoEscape(unsafe.Pointer(&old))) { ++ // Return the new head of the list. ++ e := newEntryNode(key, new) ++ if chain := head.overflow.Load(); chain != nil { ++ e.overflow.Store(chain) + } +- i := &head.overflow +- e := i.Load() +- for e != nil { +- oldvp := e.value.Load() +- if e.key == key && valEqual(unsafe.Pointer(oldvp), abi.NoEscape(unsafe.Pointer(&oldv))) { +- if vbox == nil { +- // Delay explicit creation of a new value to hold newv. If we just pass &newv +- // to CompareAndSwap, then newv will unconditionally escape, even if the CAS fails. +- vbox = new(V) +- *vbox = newv +- } +- if e.value.CompareAndSwap(oldvp, vbox) { +- return true +- } +- continue outerLoop +- } +- i = &e.overflow +- e = e.overflow.Load() ++ return e, true ++ } ++ i := &head.overflow ++ e := i.Load() ++ for e != nil { ++ if e.key == key && valEqual(unsafe.Pointer(&e.value), abi.NoEscape(unsafe.Pointer(&old))) { ++ eNew := newEntryNode(key, new) ++ eNew.overflow.Store(e.overflow.Load()) ++ i.Store(eNew) ++ return head, true + } +- return false ++ i = &e.overflow ++ e = e.overflow.Load() + } ++ return head, false + } + + // loadAndDelete deletes an entry in the overflow chain by key. Returns the value for the key, the new +@@ -693,14 +660,14 @@ outerLoop: + func (head *entry[K, V]) loadAndDelete(key K) (V, *entry[K, V], bool) { + if head.key == key { + // Drop the head of the list. +- return *head.value.Load(), head.overflow.Load(), true ++ return head.value, head.overflow.Load(), true + } + i := &head.overflow + e := i.Load() + for e != nil { + if e.key == key { + i.Store(e.overflow.Load()) +- return *e.value.Load(), head, true ++ return e.value, head, true + } + i = &e.overflow + e = e.overflow.Load() +@@ -713,14 +680,14 @@ func (head *entry[K, V]) loadAndDelete(key K) (V, *entry[K, V], bool) { + // + // compareAndDelete must be called under the mutex of the indirect node which e is a child of. + func (head *entry[K, V]) compareAndDelete(key K, value V, valEqual equalFunc) (*entry[K, V], bool) { +- if head.key == key && valEqual(unsafe.Pointer(head.value.Load()), abi.NoEscape(unsafe.Pointer(&value))) { ++ if head.key == key && valEqual(unsafe.Pointer(&head.value), abi.NoEscape(unsafe.Pointer(&value))) { + // Drop the head of the list. + return head.overflow.Load(), true + } + i := &head.overflow + e := i.Load() + for e != nil { +- if e.key == key && valEqual(unsafe.Pointer(e.value.Load()), abi.NoEscape(unsafe.Pointer(&value))) { ++ if e.key == key && valEqual(unsafe.Pointer(&e.value), abi.NoEscape(unsafe.Pointer(&value))) { + i.Store(e.overflow.Load()) + return head, true + } +diff --git a/src/internal/sync/hashtriemap_test.go b/src/internal/sync/hashtriemap_test.go +index 5476add880..d9219f841a 100644 +--- a/src/internal/sync/hashtriemap_test.go ++++ b/src/internal/sync/hashtriemap_test.go +@@ -12,6 +12,7 @@ import ( + "strconv" + "sync" + "testing" ++ "weak" + ) + + func TestHashTrieMap(t *testing.T) { +@@ -921,3 +922,61 @@ func init() { + testDataLarge[i] = fmt.Sprintf("%b", i) + } + } ++ ++// TestConcurrentCache tests HashTrieMap in a scenario where it is used as ++// the basis of a memory-efficient concurrent cache. We're specifically ++// looking to make sure that CompareAndSwap and CompareAndDelete are ++// atomic with respect to one another. When competing for the same ++// key-value pair, they must not both succeed. ++// ++// This test is a regression test for issue #70970. ++func TestConcurrentCache(t *testing.T) { ++ type dummy [32]byte ++ ++ var m isync.HashTrieMap[int, weak.Pointer[dummy]] ++ ++ type cleanupArg struct { ++ key int ++ value weak.Pointer[dummy] ++ } ++ cleanup := func(arg cleanupArg) { ++ m.CompareAndDelete(arg.key, arg.value) ++ } ++ get := func(m *isync.HashTrieMap[int, weak.Pointer[dummy]], key int) *dummy { ++ nv := new(dummy) ++ nw := weak.Make(nv) ++ for { ++ w, loaded := m.LoadOrStore(key, nw) ++ if !loaded { ++ runtime.AddCleanup(nv, cleanup, cleanupArg{key, nw}) ++ return nv ++ } ++ if v := w.Value(); v != nil { ++ return v ++ } ++ ++ // Weak pointer was reclaimed, try to replace it with nw. ++ if m.CompareAndSwap(key, w, nw) { ++ runtime.AddCleanup(nv, cleanup, cleanupArg{key, nw}) ++ return nv ++ } ++ } ++ } ++ ++ const N = 100_000 ++ const P = 5_000 ++ ++ var wg sync.WaitGroup ++ wg.Add(N) ++ for i := range N { ++ go func() { ++ defer wg.Done() ++ a := get(&m, i%P) ++ b := get(&m, i%P) ++ if a != b { ++ t.Errorf("consecutive cache reads returned different values: a != b (%p vs %p)\n", a, b) ++ } ++ }() ++ } ++ wg.Wait() ++} +diff --git a/src/internal/syscall/unix/at_fstatat.go b/src/internal/syscall/unix/at_fstatat.go +index 25de336a80..18cd62be20 100644 +--- a/src/internal/syscall/unix/at_fstatat.go ++++ b/src/internal/syscall/unix/at_fstatat.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build dragonfly || (linux && !loong64) || netbsd || (openbsd && mips64) ++//go:build dragonfly || (linux && !(loong64 || mips64 || mips64le)) || netbsd || (openbsd && mips64) + + package unix + +diff --git a/src/internal/syscall/unix/at_fstatat2.go b/src/internal/syscall/unix/at_fstatat2.go +index 8d20e1a885..b09aecbcdd 100644 +--- a/src/internal/syscall/unix/at_fstatat2.go ++++ b/src/internal/syscall/unix/at_fstatat2.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build freebsd || (linux && loong64) ++//go:build freebsd || (linux && (loong64 || mips64 || mips64le)) + + package unix + +diff --git a/src/iter/iter.go b/src/iter/iter.go +index 14fd8f8115..e765378ef2 100644 +--- a/src/iter/iter.go ++++ b/src/iter/iter.go +@@ -28,7 +28,22 @@ or index-value pairs. + Yield returns true if the iterator should continue with the next + element in the sequence, false if it should stop. + +-Iterator functions are most often called by a range loop, as in: ++For instance, [maps.Keys] returns an iterator that produces the sequence ++of keys of the map m, implemented as follows: ++ ++ func Keys[Map ~map[K]V, K comparable, V any](m Map) iter.Seq[K] { ++ return func(yield func(K) bool) { ++ for k := range m { ++ if !yield(k) { ++ return ++ } ++ } ++ } ++ } ++ ++Further examples can be found in [The Go Blog: Range Over Function Types]. ++ ++Iterator functions are most often called by a [range loop], as in: + + func PrintAll[V any](seq iter.Seq[V]) { + for v := range seq { +@@ -187,6 +202,9 @@ And then a client could delete boring values from the tree using: + p.Delete() + } + } ++ ++[The Go Blog: Range Over Function Types]: https://go.dev/blog/range-functions ++[range loop]: https://go.dev/ref/spec#For_range + */ + package iter + +diff --git a/src/net/example_test.go b/src/net/example_test.go +index 2c045d73a2..12c8397094 100644 +--- a/src/net/example_test.go ++++ b/src/net/example_test.go +@@ -334,7 +334,7 @@ func ExampleIP_To16() { + // 10.255.0.0 + } + +-func ExampleIP_to4() { ++func ExampleIP_To4() { + ipv6 := net.IP{0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + ipv4 := net.IPv4(10, 255, 0, 0) + +diff --git a/src/net/http/request.go b/src/net/http/request.go +index 686d53345a..434c1640f3 100644 +--- a/src/net/http/request.go ++++ b/src/net/http/request.go +@@ -873,9 +873,9 @@ func NewRequest(method, url string, body io.Reader) (*Request, error) { + // + // NewRequestWithContext returns a Request suitable for use with + // [Client.Do] or [Transport.RoundTrip]. To create a request for use with +-// testing a Server Handler, either use the [NewRequest] function in the +-// net/http/httptest package, use [ReadRequest], or manually update the +-// Request fields. For an outgoing client request, the context ++// testing a Server Handler, either use the [net/http/httptest.NewRequest] function, ++// use [ReadRequest], or manually update the Request fields. ++// For an outgoing client request, the context + // controls the entire lifetime of a request and its response: + // obtaining a connection, sending the request, and reading the + // response headers and body. See the Request type's documentation for +diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go +index 2963255b87..a454db5e03 100644 +--- a/src/net/http/transport_test.go ++++ b/src/net/http/transport_test.go +@@ -5500,7 +5500,9 @@ timeoutLoop: + return false + } + } +- res.Body.Close() ++ if err == nil { ++ res.Body.Close() ++ } + conns := idleConns() + if len(conns) != 1 { + if len(conns) == 0 { +diff --git a/src/net/lookup.go b/src/net/lookup.go +index b04dfa23b9..f94fd8cefa 100644 +--- a/src/net/lookup.go ++++ b/src/net/lookup.go +@@ -614,6 +614,9 @@ func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) { + + // LookupTXT returns the DNS TXT records for the given domain name. + // ++// If a DNS TXT record holds multiple strings, they are concatenated as a ++// single string. ++// + // LookupTXT uses [context.Background] internally; to specify the context, use + // [Resolver.LookupTXT]. + func LookupTXT(name string) ([]string, error) { +@@ -621,6 +624,9 @@ func LookupTXT(name string) ([]string, error) { + } + + // LookupTXT returns the DNS TXT records for the given domain name. ++// ++// If a DNS TXT record holds multiple strings, they are concatenated as a ++// single string. + func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) { + return r.lookupTXT(ctx, name) + } +diff --git a/src/os/dir.go b/src/os/dir.go +index 04392193aa..939b208d8c 100644 +--- a/src/os/dir.go ++++ b/src/os/dir.go +@@ -145,6 +145,9 @@ func ReadDir(name string) ([]DirEntry, error) { + // + // Symbolic links in dir are followed. + // ++// New files added to fsys (including if dir is a subdirectory of fsys) ++// while CopyFS is running are not guaranteed to be copied. ++// + // Copying stops at and returns the first error encountered. + func CopyFS(dir string, fsys fs.FS) error { + return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { +diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go +index 268ddb59c9..236c32ea34 100644 +--- a/src/runtime/crash_test.go ++++ b/src/runtime/crash_test.go +@@ -32,8 +32,11 @@ const entrypointVar = "RUNTIME_TEST_ENTRYPOINT" + + func TestMain(m *testing.M) { + switch entrypoint := os.Getenv(entrypointVar); entrypoint { +- case "crash": +- crash() ++ case "panic": ++ crashViaPanic() ++ panic("unreachable") ++ case "trap": ++ crashViaTrap() + panic("unreachable") + default: + log.Fatalf("invalid %s: %q", entrypointVar, entrypoint) +diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go +index 35cb634936..00280ed1b5 100644 +--- a/src/runtime/gc_test.go ++++ b/src/runtime/gc_test.go +@@ -834,7 +834,11 @@ func TestWeakToStrongMarkTermination(t *testing.T) { + done <- struct{}{} + }() + go func() { +- time.Sleep(100 * time.Millisecond) ++ // Usleep here instead of time.Sleep. time.Sleep ++ // can allocate, and if we get unlucky, then it ++ // can end up stuck in gcMarkDone with nothing to ++ // wake it. ++ runtime.Usleep(100000) // 100ms + + // Let mark termination continue. + runtime.SetSpinInGCMarkDone(false) +diff --git a/src/runtime/map_swiss.go b/src/runtime/map_swiss.go +index 75c72b20f5..e6e29bcfb8 100644 +--- a/src/runtime/map_swiss.go ++++ b/src/runtime/map_swiss.go +@@ -39,6 +39,16 @@ func makemap64(t *abi.SwissMapType, hint int64, m *maps.Map) *maps.Map { + // makemap_small implements Go map creation for make(map[k]v) and + // make(map[k]v, hint) when hint is known to be at most abi.SwissMapGroupSlots + // at compile time and the map needs to be allocated on the heap. ++// ++// makemap_small should be an internal detail, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/bytedance/sonic ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// ++//go:linkname makemap_small + func makemap_small() *maps.Map { + return maps.NewEmptyMap() + } +@@ -48,6 +58,16 @@ func makemap_small() *maps.Map { + // can be created on the stack, m and optionally m.dirPtr may be non-nil. + // If m != nil, the map can be created directly in m. + // If m.dirPtr != nil, it points to a group usable for a small map. ++// ++// makemap should be an internal detail, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/ugorji/go/codec ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// ++//go:linkname makemap + func makemap(t *abi.SwissMapType, hint int, m *maps.Map) *maps.Map { + if hint < 0 { + hint = 0 +@@ -68,6 +88,15 @@ func makemap(t *abi.SwissMapType, hint int, m *maps.Map) *maps.Map { + //go:linkname mapaccess1 + func mapaccess1(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) unsafe.Pointer + ++// mapaccess2 should be an internal detail, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/ugorji/go/codec ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// ++//go:linkname mapaccess2 + func mapaccess2(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) (unsafe.Pointer, bool) + + func mapaccess1_fat(t *abi.SwissMapType, m *maps.Map, key, zero unsafe.Pointer) unsafe.Pointer { +@@ -89,9 +118,29 @@ func mapaccess2_fat(t *abi.SwissMapType, m *maps.Map, key, zero unsafe.Pointer) + // mapassign is pushed from internal/runtime/maps. We could just call it, but + // we want to avoid one layer of call. + // ++// mapassign should be an internal detail, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/bytedance/sonic ++// - github.com/RomiChan/protobuf ++// - github.com/segmentio/encoding ++// - github.com/ugorji/go/codec ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// + //go:linkname mapassign + func mapassign(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) unsafe.Pointer + ++// mapdelete should be an internal detail, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/ugorji/go/codec ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// ++//go:linkname mapdelete + func mapdelete(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) { + if raceenabled && m != nil { + callerpc := sys.GetCallerPC() +@@ -113,6 +162,21 @@ func mapdelete(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) { + // The Iter struct pointed to by 'it' is allocated on the stack + // by the compilers order pass or on the heap by reflect_mapiterinit. + // Both need to have zeroed hiter since the struct contains pointers. ++// ++// mapiterinit should be an internal detail, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/bytedance/sonic ++// - github.com/goccy/go-json ++// - github.com/RomiChan/protobuf ++// - github.com/segmentio/encoding ++// - github.com/ugorji/go/codec ++// - github.com/wI2L/jettison ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// ++//go:linkname mapiterinit + func mapiterinit(t *abi.SwissMapType, m *maps.Map, it *maps.Iter) { + if raceenabled && m != nil { + callerpc := sys.GetCallerPC() +@@ -123,6 +187,19 @@ func mapiterinit(t *abi.SwissMapType, m *maps.Map, it *maps.Iter) { + it.Next() + } + ++// mapiternext should be an internal detail, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/bytedance/sonic ++// - github.com/RomiChan/protobuf ++// - github.com/segmentio/encoding ++// - github.com/ugorji/go/codec ++// - gonum.org/v1/gonum ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// ++//go:linkname mapiternext + func mapiternext(it *maps.Iter) { + if raceenabled { + callerpc := sys.GetCallerPC() +@@ -145,6 +222,19 @@ func mapclear(t *abi.SwissMapType, m *maps.Map) { + + // Reflect stubs. Called from ../reflect/asm_*.s + ++// reflect_makemap is for package reflect, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - gitee.com/quant1x/gox ++// - github.com/modern-go/reflect2 ++// - github.com/goccy/go-json ++// - github.com/RomiChan/protobuf ++// - github.com/segmentio/encoding ++// - github.com/v2pro/plz ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// + //go:linkname reflect_makemap reflect.makemap + func reflect_makemap(t *abi.SwissMapType, cap int) *maps.Map { + // Check invariants and reflects math. +@@ -156,6 +246,16 @@ func reflect_makemap(t *abi.SwissMapType, cap int) *maps.Map { + return makemap(t, cap, nil) + } + ++// reflect_mapaccess is for package reflect, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - gitee.com/quant1x/gox ++// - github.com/modern-go/reflect2 ++// - github.com/v2pro/plz ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// + //go:linkname reflect_mapaccess reflect.mapaccess + func reflect_mapaccess(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) unsafe.Pointer { + elem, ok := mapaccess2(t, m, key) +@@ -176,6 +276,14 @@ func reflect_mapaccess_faststr(t *abi.SwissMapType, m *maps.Map, key string) uns + return elem + } + ++// reflect_mapassign is for package reflect, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - gitee.com/quant1x/gox ++// - github.com/v2pro/plz ++// ++// Do not remove or change the type signature. ++// + //go:linkname reflect_mapassign reflect.mapassign0 + func reflect_mapassign(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer, elem unsafe.Pointer) { + p := mapassign(t, m, key) +@@ -198,26 +306,76 @@ func reflect_mapdelete_faststr(t *abi.SwissMapType, m *maps.Map, key string) { + mapdelete_faststr(t, m, key) + } + ++// reflect_mapiterinit is for package reflect, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/modern-go/reflect2 ++// - gitee.com/quant1x/gox ++// - github.com/v2pro/plz ++// - github.com/wI2L/jettison ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// + //go:linkname reflect_mapiterinit reflect.mapiterinit + func reflect_mapiterinit(t *abi.SwissMapType, m *maps.Map, it *maps.Iter) { + mapiterinit(t, m, it) + } + ++// reflect_mapiternext is for package reflect, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - gitee.com/quant1x/gox ++// - github.com/modern-go/reflect2 ++// - github.com/goccy/go-json ++// - github.com/v2pro/plz ++// - github.com/wI2L/jettison ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// + //go:linkname reflect_mapiternext reflect.mapiternext + func reflect_mapiternext(it *maps.Iter) { + mapiternext(it) + } + ++// reflect_mapiterkey was for package reflect, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/goccy/go-json ++// - gonum.org/v1/gonum ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// + //go:linkname reflect_mapiterkey reflect.mapiterkey + func reflect_mapiterkey(it *maps.Iter) unsafe.Pointer { + return it.Key() + } + ++// reflect_mapiterelem was for package reflect, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/goccy/go-json ++// - gonum.org/v1/gonum ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// + //go:linkname reflect_mapiterelem reflect.mapiterelem + func reflect_mapiterelem(it *maps.Iter) unsafe.Pointer { + return it.Elem() + } + ++// reflect_maplen is for package reflect, ++// but widely used packages access it using linkname. ++// Notable members of the hall of shame include: ++// - github.com/goccy/go-json ++// - github.com/wI2L/jettison ++// ++// Do not remove or change the type signature. ++// See go.dev/issue/67401. ++// + //go:linkname reflect_maplen reflect.maplen + func reflect_maplen(m *maps.Map) int { + if m == nil { +diff --git a/src/runtime/pprof/vminfo_darwin_test.go b/src/runtime/pprof/vminfo_darwin_test.go +index 4c0a0fefd8..6d375c5d53 100644 +--- a/src/runtime/pprof/vminfo_darwin_test.go ++++ b/src/runtime/pprof/vminfo_darwin_test.go +@@ -97,7 +97,7 @@ func useVMMap(t *testing.T) (hi, lo uint64, retryable bool, err error) { + t.Logf("vmmap output: %s", out) + if ee, ok := cmdErr.(*exec.ExitError); ok && len(ee.Stderr) > 0 { + t.Logf("%v: %v\n%s", cmd, cmdErr, ee.Stderr) +- if testing.Short() && strings.Contains(string(ee.Stderr), "No process corpse slots currently available, waiting to get one") { ++ if testing.Short() && (strings.Contains(string(ee.Stderr), "No process corpse slots currently available, waiting to get one") || strings.Contains(string(ee.Stderr), "Failed to generate corpse from the process")) { + t.Skipf("Skipping knwn flake in short test mode") + } + retryable = bytes.Contains(ee.Stderr, []byte("resource shortage")) +diff --git a/src/runtime/proc.go b/src/runtime/proc.go +index 6362960200..e9873e54cd 100644 +--- a/src/runtime/proc.go ++++ b/src/runtime/proc.go +@@ -3894,23 +3894,23 @@ func injectglist(glist *gList) { + if glist.empty() { + return + } +- trace := traceAcquire() +- if trace.ok() { +- for gp := glist.head.ptr(); gp != nil; gp = gp.schedlink.ptr() { +- trace.GoUnpark(gp, 0) +- } +- traceRelease(trace) +- } + + // Mark all the goroutines as runnable before we put them + // on the run queues. + head := glist.head.ptr() + var tail *g + qsize := 0 ++ trace := traceAcquire() + for gp := head; gp != nil; gp = gp.schedlink.ptr() { + tail = gp + qsize++ + casgstatus(gp, _Gwaiting, _Grunnable) ++ if trace.ok() { ++ trace.GoUnpark(gp, 0) ++ } ++ } ++ if trace.ok() { ++ traceRelease(trace) + } + + // Turn the gList into a gQueue. +diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go +index c78b044264..c3bd510320 100644 +--- a/src/runtime/symtab.go ++++ b/src/runtime/symtab.go +@@ -468,6 +468,18 @@ type modulehash struct { + // To make sure the map isn't collected, we keep a second reference here. + var pinnedTypemaps []map[typeOff]*_type + ++// aixStaticDataBase (used only on AIX) holds the unrelocated address ++// of the data section, set by the linker. ++// ++// On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol ++// does not work, as the dynamic loader can change the address of the ++// data section, and it is not possible to apply a dynamic relocation ++// to RODATA. In order to get the correct address, we need to apply ++// the delta between unrelocated and relocated data section addresses. ++// aixStaticDataBase is the unrelocated address, and moduledata.data is ++// the relocated one. ++var aixStaticDataBase uintptr // linker symbol ++ + var firstmoduledata moduledata // linker symbol + var lastmoduledatap *moduledata // linker symbol + +diff --git a/src/runtime/traceback_system_test.go b/src/runtime/traceback_system_test.go +index ece58e806d..af20f54a09 100644 +--- a/src/runtime/traceback_system_test.go ++++ b/src/runtime/traceback_system_test.go +@@ -23,8 +23,8 @@ import ( + ) + + // This is the entrypoint of the child process used by +-// TestTracebackSystem. It prints a crash report to stdout. +-func crash() { ++// TestTracebackSystem/panic. It prints a crash report to stdout. ++func crashViaPanic() { + // Ensure that we get pc=0x%x values in the traceback. + debug.SetTraceback("system") + writeSentinel(os.Stdout) +@@ -37,6 +37,21 @@ func crash() { + select {} + } + ++// This is the entrypoint of the child process used by ++// TestTracebackSystem/trap. It prints a crash report to stdout. ++func crashViaTrap() { ++ // Ensure that we get pc=0x%x values in the traceback. ++ debug.SetTraceback("system") ++ writeSentinel(os.Stdout) ++ debug.SetCrashOutput(os.Stdout, debug.CrashOptions{}) ++ ++ go func() { ++ // This call is typically inlined. ++ trap1() ++ }() ++ select {} ++} ++ + func child1() { + child2() + } +@@ -85,6 +100,20 @@ func child7() { + panic("oops") + } + ++func trap1() { ++ trap2() ++} ++ ++var sinkPtr *int ++ ++func trap2() { ++ trap3(sinkPtr) ++} ++ ++func trap3(i *int) { ++ *i = 42 ++} ++ + // TestTracebackSystem tests that the syntax of crash reports produced + // by GOTRACEBACK=system (see traceback2) contains a complete, + // parseable list of program counters for the running goroutine that +@@ -100,46 +129,75 @@ func TestTracebackSystem(t *testing.T) { + t.Skip("Can't read source code for this file on Android") + } + +- // Fork+exec the crashing process. +- exe, err := os.Executable() +- if err != nil { +- t.Fatal(err) +- } +- cmd := testenv.Command(t, exe) +- cmd.Env = append(cmd.Environ(), entrypointVar+"=crash") +- var stdout, stderr bytes.Buffer +- cmd.Stdout = &stdout +- cmd.Stderr = &stderr +- cmd.Run() // expected to crash +- t.Logf("stderr:\n%s\nstdout: %s\n", stderr.Bytes(), stdout.Bytes()) +- crash := stdout.String() +- +- // If the only line is the sentinel, it wasn't a crash. +- if strings.Count(crash, "\n") < 2 { +- t.Fatalf("child process did not produce a crash report") ++ tests := []struct{ ++ name string ++ want string ++ }{ ++ { ++ name: "panic", ++ want: `redacted.go:0: runtime.gopanic ++traceback_system_test.go:100: runtime_test.child7: panic("oops") ++traceback_system_test.go:83: runtime_test.child6: child7() // appears in stack trace ++traceback_system_test.go:74: runtime_test.child5: child6() // appears in stack trace ++traceback_system_test.go:68: runtime_test.child4: child5() ++traceback_system_test.go:64: runtime_test.child3: child4() ++traceback_system_test.go:60: runtime_test.child2: child3() ++traceback_system_test.go:56: runtime_test.child1: child2() ++traceback_system_test.go:35: runtime_test.crashViaPanic.func1: child1() ++redacted.go:0: runtime.goexit ++`, ++ }, ++ { ++ // Test panic via trap. x/telemetry is aware that trap ++ // PCs follow runtime.sigpanic and need to be ++ // incremented to offset the decrement done by ++ // CallersFrames. ++ name: "trap", ++ want: `redacted.go:0: runtime.gopanic ++redacted.go:0: runtime.panicmem ++redacted.go:0: runtime.sigpanic ++traceback_system_test.go:114: runtime_test.trap3: *i = 42 ++traceback_system_test.go:110: runtime_test.trap2: trap3(sinkPtr) ++traceback_system_test.go:104: runtime_test.trap1: trap2() ++traceback_system_test.go:50: runtime_test.crashViaTrap.func1: trap1() ++redacted.go:0: runtime.goexit ++`, ++ }, + } + +- // Parse the PCs out of the child's crash report. +- pcs, err := parseStackPCs(crash) +- if err != nil { +- t.Fatal(err) +- } ++ for _, tc := range tests { ++ t.Run(tc.name, func(t *testing.T) { ++ // Fork+exec the crashing process. ++ exe, err := os.Executable() ++ if err != nil { ++ t.Fatal(err) ++ } ++ cmd := testenv.Command(t, exe) ++ cmd.Env = append(cmd.Environ(), entrypointVar+"="+tc.name) ++ var stdout, stderr bytes.Buffer ++ cmd.Stdout = &stdout ++ cmd.Stderr = &stderr ++ cmd.Run() // expected to crash ++ t.Logf("stderr:\n%s\nstdout: %s\n", stderr.Bytes(), stdout.Bytes()) ++ crash := stdout.String() ++ ++ // If the only line is the sentinel, it wasn't a crash. ++ if strings.Count(crash, "\n") < 2 { ++ t.Fatalf("child process did not produce a crash report") ++ } + +- // Unwind the stack using this executable's symbol table. +- got := formatStack(pcs) +- want := `redacted.go:0: runtime.gopanic +-traceback_system_test.go:85: runtime_test.child7: panic("oops") +-traceback_system_test.go:68: runtime_test.child6: child7() // appears in stack trace +-traceback_system_test.go:59: runtime_test.child5: child6() // appears in stack trace +-traceback_system_test.go:53: runtime_test.child4: child5() +-traceback_system_test.go:49: runtime_test.child3: child4() +-traceback_system_test.go:45: runtime_test.child2: child3() +-traceback_system_test.go:41: runtime_test.child1: child2() +-traceback_system_test.go:35: runtime_test.crash.func1: child1() +-redacted.go:0: runtime.goexit +-` +- if strings.TrimSpace(got) != strings.TrimSpace(want) { +- t.Errorf("got:\n%swant:\n%s", got, want) ++ // Parse the PCs out of the child's crash report. ++ pcs, err := parseStackPCs(crash) ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ // Unwind the stack using this executable's symbol table. ++ got := formatStack(pcs) ++ if strings.TrimSpace(got) != strings.TrimSpace(tc.want) { ++ t.Errorf("got:\n%swant:\n%s", got, tc.want) ++ } ++ }) + } + } + +@@ -154,6 +212,35 @@ redacted.go:0: runtime.goexit + // + // (Copied from golang.org/x/telemetry/crashmonitor.parseStackPCs.) + func parseStackPCs(crash string) ([]uintptr, error) { ++ // getSymbol parses the symbol name out of a line of the form: ++ // SYMBOL(ARGS) ++ // ++ // Note: SYMBOL may contain parens "pkg.(*T).method". However, type ++ // parameters are always replaced with ..., so they cannot introduce ++ // more parens. e.g., "pkg.(*T[...]).method". ++ // ++ // ARGS can contain parens. We want the first paren that is not ++ // immediately preceded by a ".". ++ // ++ // TODO(prattmic): This is mildly complicated and is only used to find ++ // runtime.sigpanic, so perhaps simplify this by checking explicitly ++ // for sigpanic. ++ getSymbol := func(line string) (string, error) { ++ var prev rune ++ for i, c := range line { ++ if line[i] != '(' { ++ prev = c ++ continue ++ } ++ if prev == '.' { ++ prev = c ++ continue ++ } ++ return line[:i], nil ++ } ++ return "", fmt.Errorf("no symbol for stack frame: %s", line) ++ } ++ + // getPC parses the PC out of a line of the form: + // \tFILE:LINE +0xRELPC sp=... fp=... pc=... + getPC := func(line string) (uint64, error) { +@@ -170,6 +257,9 @@ func parseStackPCs(crash string) ([]uintptr, error) { + childSentinel = sentinel() + on = false // are we in the first running goroutine? + lines = strings.Split(crash, "\n") ++ symLine = true // within a goroutine, every other line is a symbol or file/line/pc location, starting with symbol. ++ currSymbol string ++ prevSymbol string // symbol of the most recent previous frame with a PC. + ) + for i := 0; i < len(lines); i++ { + line := lines[i] +@@ -212,21 +302,76 @@ func parseStackPCs(crash string) ([]uintptr, error) { + // Note: SYMBOL may contain parens "pkg.(*T).method" + // The RELPC is sometimes missing. + +- // Skip the symbol(args) line. +- i++ +- if i == len(lines) { +- break +- } +- line = lines[i] ++ if symLine { ++ var err error ++ currSymbol, err = getSymbol(line) ++ if err != nil { ++ return nil, fmt.Errorf("error extracting symbol: %v", err) ++ } + +- // Parse the PC, and correct for the parent and child's +- // different mappings of the text section. +- pc, err := getPC(line) +- if err != nil { +- // Inlined frame, perhaps; skip it. +- continue ++ symLine = false // Next line is FILE:LINE. ++ } else { ++ // Parse the PC, and correct for the parent and child's ++ // different mappings of the text section. ++ pc, err := getPC(line) ++ if err != nil { ++ // Inlined frame, perhaps; skip it. ++ ++ // Done with this frame. Next line is a new frame. ++ // ++ // Don't update prevSymbol; we only want to ++ // track frames with a PC. ++ currSymbol = "" ++ symLine = true ++ continue ++ } ++ ++ pc = pc-parentSentinel+childSentinel ++ ++ // If the previous frame was sigpanic, then this frame ++ // was a trap (e.g., SIGSEGV). ++ // ++ // Typically all middle frames are calls, and report ++ // the "return PC". That is, the instruction following ++ // the CALL where the callee will eventually return to. ++ // ++ // runtime.CallersFrames is aware of this property and ++ // will decrement each PC by 1 to "back up" to the ++ // location of the CALL, which is the actual line ++ // number the user expects. ++ // ++ // This does not work for traps, as a trap is not a ++ // call, so the reported PC is not the return PC, but ++ // the actual PC of the trap. ++ // ++ // runtime.Callers is aware of this and will ++ // intentionally increment trap PCs in order to correct ++ // for the decrement performed by ++ // runtime.CallersFrames. See runtime.tracebackPCs and ++ // runtume.(*unwinder).symPC. ++ // ++ // We must emulate the same behavior, otherwise we will ++ // report the location of the instruction immediately ++ // prior to the trap, which may be on a different line, ++ // or even a different inlined functions. ++ // ++ // TODO(prattmic): The runtime applies the same trap ++ // behavior for other "injected calls", see injectCall ++ // in runtime.(*unwinder).next. Do we want to handle ++ // those as well? I don't believe we'd ever see ++ // runtime.asyncPreempt or runtime.debugCallV2 in a ++ // typical crash. ++ if prevSymbol == "runtime.sigpanic" { ++ pc++ ++ } ++ ++ pcs = append(pcs, uintptr(pc)) ++ ++ // Done with this frame. Next line is a new frame. ++ prevSymbol = currSymbol ++ currSymbol = "" ++ symLine = true + } +- pcs = append(pcs, uintptr(pc-parentSentinel+childSentinel)) + } + return pcs, nil + } +diff --git a/src/runtime/type.go b/src/runtime/type.go +index 9702164b1a..1edf9c9dd6 100644 +--- a/src/runtime/type.go ++++ b/src/runtime/type.go +@@ -104,6 +104,10 @@ func getGCMaskOnDemand(t *_type) *byte { + // in read-only memory currently. + addr := unsafe.Pointer(t.GCData) + ++ if GOOS == "aix" { ++ addr = add(addr, firstmoduledata.data-aixStaticDataBase) ++ } ++ + for { + p := (*byte)(atomic.Loadp(addr)) + switch p { +diff --git a/src/slices/slices.go b/src/slices/slices.go +index 40b4d088b0..32029cd8ed 100644 +--- a/src/slices/slices.go ++++ b/src/slices/slices.go +@@ -414,6 +414,7 @@ func Grow[S ~[]E, E any](s S, n int) S { + panic("cannot be negative") + } + if n -= cap(s) - len(s); n > 0 { ++ // This expression allocates only once (see test). + s = append(s[:cap(s)], make([]E, n)...)[:len(s)] + } + return s +@@ -483,6 +484,9 @@ func Concat[S ~[]E, E any](slices ...S) S { + panic("len out of range") + } + } ++ // Use Grow, not make, to round up to the size class: ++ // the extra space is otherwise unused and helps ++ // callers that append a few elements to the result. + newslice := Grow[S](nil, size) + for _, s := range slices { + newslice = append(newslice, s...) +diff --git a/src/strconv/ftoa.go b/src/strconv/ftoa.go +index 6db0d47e0f..bfe26366e1 100644 +--- a/src/strconv/ftoa.go ++++ b/src/strconv/ftoa.go +@@ -44,6 +44,8 @@ var float64info = floatInfo{52, 11, -1023} + // zeros are removed). + // The special precision -1 uses the smallest number of digits + // necessary such that ParseFloat will return f exactly. ++// The exponent is written as a decimal integer; ++// for all formats other than 'b', it will be at least two digits. + func FormatFloat(f float64, fmt byte, prec, bitSize int) string { + return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize)) + } +diff --git a/src/strings/iter.go b/src/strings/iter.go +index b9620902bf..3168e59687 100644 +--- a/src/strings/iter.go ++++ b/src/strings/iter.go +@@ -68,7 +68,7 @@ func splitSeq(s, sep string, sepSave int) iter.Seq[string] { + } + + // SplitSeq returns an iterator over all substrings of s separated by sep. +-// The iterator yields the same strings that would be returned by Split(s, sep), ++// The iterator yields the same strings that would be returned by [Split](s, sep), + // but without constructing the slice. + // It returns a single-use iterator. + func SplitSeq(s, sep string) iter.Seq[string] { +@@ -76,7 +76,7 @@ func SplitSeq(s, sep string) iter.Seq[string] { + } + + // SplitAfterSeq returns an iterator over substrings of s split after each instance of sep. +-// The iterator yields the same strings that would be returned by SplitAfter(s, sep), ++// The iterator yields the same strings that would be returned by [SplitAfter](s, sep), + // but without constructing the slice. + // It returns a single-use iterator. + func SplitAfterSeq(s, sep string) iter.Seq[string] { +@@ -84,8 +84,8 @@ func SplitAfterSeq(s, sep string) iter.Seq[string] { + } + + // FieldsSeq returns an iterator over substrings of s split around runs of +-// whitespace characters, as defined by unicode.IsSpace. +-// The iterator yields the same strings that would be returned by Fields(s), ++// whitespace characters, as defined by [unicode.IsSpace]. ++// The iterator yields the same strings that would be returned by [Fields](s), + // but without constructing the slice. + func FieldsSeq(s string) iter.Seq[string] { + return func(yield func(string) bool) { +@@ -118,7 +118,7 @@ func FieldsSeq(s string) iter.Seq[string] { + + // FieldsFuncSeq returns an iterator over substrings of s split around runs of + // Unicode code points satisfying f(c). +-// The iterator yields the same strings that would be returned by FieldsFunc(s), ++// The iterator yields the same strings that would be returned by [FieldsFunc](s), + // but without constructing the slice. + func FieldsFuncSeq(s string, f func(rune) bool) iter.Seq[string] { + return func(yield func(string) bool) { +diff --git a/src/syscall/syscall_freebsd_386.go b/src/syscall/syscall_freebsd_386.go +index 60359e38f6..a217dc758b 100644 +--- a/src/syscall/syscall_freebsd_386.go ++++ b/src/syscall/syscall_freebsd_386.go +@@ -36,7 +36,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e + var writtenOut uint64 = 0 + _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr((*offset)>>32), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0) + +- written = int(writtenOut) ++ // For some reason on the freebsd-386 builder writtenOut ++ // is modified when the system call returns EINVAL. ++ // The man page says that the value is only written for ++ // success, EINTR, or EAGAIN, so only use those cases. ++ if e1 == 0 || e1 == EINTR || e1 == EAGAIN { ++ written = int(writtenOut) ++ } + + if e1 != 0 { + err = e1 +diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go +index 51f5ead472..e826e08615 100644 +--- a/src/syscall/syscall_linux_mips64x.go ++++ b/src/syscall/syscall_linux_mips64x.go +@@ -16,7 +16,6 @@ const ( + //sys Dup2(oldfd int, newfd int) (err error) + //sys Fchown(fd int, uid int, gid int) (err error) + //sys Fstatfs(fd int, buf *Statfs_t) (err error) +-//sys fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT + //sys Ftruncate(fd int, length int64) (err error) + //sysnb Getegid() (egid int) + //sysnb Geteuid() (euid int) +@@ -126,10 +125,22 @@ type stat_t struct { + Blocks int64 + } + ++//sys fstatatInternal(dirfd int, path string, stat *stat_t, flags int) (err error) = SYS_NEWFSTATAT + //sys fstat(fd int, st *stat_t) (err error) + //sys lstat(path string, st *stat_t) (err error) + //sys stat(path string, st *stat_t) (err error) + ++func fstatat(fd int, path string, s *Stat_t, flags int) (err error) { ++ st := &stat_t{} ++ err = fstatatInternal(fd, path, st, flags) ++ fillStat_t(s, st) ++ return ++} ++ ++func Fstatat(fd int, path string, s *Stat_t, flags int) (err error) { ++ return fstatat(fd, path, s, flags) ++} ++ + func Fstat(fd int, s *Stat_t) (err error) { + st := &stat_t{} + err = fstat(fd, st) +diff --git a/src/syscall/zsyscall_linux_mips64.go b/src/syscall/zsyscall_linux_mips64.go +index 0352ea5420..449088c815 100644 +--- a/src/syscall/zsyscall_linux_mips64.go ++++ b/src/syscall/zsyscall_linux_mips64.go +@@ -1116,21 +1116,6 @@ func Fstatfs(fd int, buf *Statfs_t) (err error) { + + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +-func fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { +- var _p0 *byte +- _p0, err = BytePtrFromString(path) +- if err != nil { +- return +- } +- _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) +- if e1 != 0 { +- err = errnoErr(e1) +- } +- return +-} +- +-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +- + func Ftruncate(fd int, length int64) (err error) { + _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0) + if e1 != 0 { +@@ -1638,6 +1623,21 @@ func utimes(path string, times *[2]Timeval) (err error) { + + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + ++func fstatatInternal(dirfd int, path string, stat *stat_t, flags int) (err error) { ++ var _p0 *byte ++ _p0, err = BytePtrFromString(path) ++ if err != nil { ++ return ++ } ++ _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) ++ if e1 != 0 { ++ err = errnoErr(e1) ++ } ++ return ++} ++ ++// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT ++ + func fstat(fd int, st *stat_t) (err error) { + _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(st)), 0) + if e1 != 0 { +diff --git a/src/syscall/zsyscall_linux_mips64le.go b/src/syscall/zsyscall_linux_mips64le.go +index 1338b8c1c3..048298a39c 100644 +--- a/src/syscall/zsyscall_linux_mips64le.go ++++ b/src/syscall/zsyscall_linux_mips64le.go +@@ -1116,21 +1116,6 @@ func Fstatfs(fd int, buf *Statfs_t) (err error) { + + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +-func fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { +- var _p0 *byte +- _p0, err = BytePtrFromString(path) +- if err != nil { +- return +- } +- _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) +- if e1 != 0 { +- err = errnoErr(e1) +- } +- return +-} +- +-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +- + func Ftruncate(fd int, length int64) (err error) { + _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0) + if e1 != 0 { +@@ -1638,6 +1623,21 @@ func utimes(path string, times *[2]Timeval) (err error) { + + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + ++func fstatatInternal(dirfd int, path string, stat *stat_t, flags int) (err error) { ++ var _p0 *byte ++ _p0, err = BytePtrFromString(path) ++ if err != nil { ++ return ++ } ++ _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) ++ if e1 != 0 { ++ err = errnoErr(e1) ++ } ++ return ++} ++ ++// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT ++ + func fstat(fd int, st *stat_t) (err error) { + _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(st)), 0) + if e1 != 0 { +diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go +index 78e1b2de6d..3a7da9e540 100644 +--- a/src/testing/benchmark.go ++++ b/src/testing/benchmark.go +@@ -5,6 +5,7 @@ + package testing + + import ( ++ "context" + "flag" + "fmt" + "internal/sysinfo" +@@ -78,7 +79,7 @@ type InternalBenchmark struct { + } + + // B is a type passed to [Benchmark] functions to manage benchmark +-// timing and to specify the number of iterations to run. ++// timing and control the number of iterations. + // + // A benchmark ends when its Benchmark function returns or calls any of the methods + // FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods must be called +@@ -133,8 +134,7 @@ func (b *B) StartTimer() { + } + + // StopTimer stops timing a test. This can be used to pause the timer +-// while performing complex initialization that you don't +-// want to measure. ++// while performing steps that you don't want to measure. + func (b *B) StopTimer() { + if b.timerOn { + b.duration += highPrecisionTimeSince(b.start) +@@ -182,6 +182,7 @@ func (b *B) ReportAllocs() { + func (b *B) runN(n int) { + benchmarkLock.Lock() + defer benchmarkLock.Unlock() ++ ctx, cancelCtx := context.WithCancel(context.Background()) + defer func() { + b.runCleanup(normalPanic) + b.checkRaces() +@@ -192,6 +193,8 @@ func (b *B) runN(n int) { + b.resetRaces() + b.N = n + b.loopN = 0 ++ b.ctx = ctx ++ b.cancelCtx = cancelCtx + + b.parallelism = 1 + b.ResetTimer() +@@ -367,6 +370,8 @@ func (b *B) ReportMetric(n float64, unit string) { + func (b *B) stopOrScaleBLoop() bool { + timeElapsed := highPrecisionTimeSince(b.start) + if timeElapsed >= b.benchTime.d { ++ // Stop the timer so we don't count cleanup time ++ b.StopTimer() + return false + } + // Loop scaling +@@ -387,40 +392,53 @@ func (b *B) loopSlowPath() bool { + b.ResetTimer() + return true + } +- // Handles fixed time case ++ // Handles fixed iterations case + if b.benchTime.n > 0 { + if b.N < b.benchTime.n { + b.N = b.benchTime.n + b.loopN++ + return true + } ++ b.StopTimer() + return false + } +- // Handles fixed iteration count case ++ // Handles fixed time case + return b.stopOrScaleBLoop() + } + +-// Loop returns true until b.N calls has been made to it. +-// +-// A benchmark should either use Loop or contain an explicit loop from 0 to b.N, but not both. +-// After the benchmark finishes, b.N will contain the total number of calls to op, so the benchmark +-// may use b.N to compute other average metrics. ++// Loop returns true as long as the benchmark should continue running. + // +-// The parameters and results of function calls inside the body of "for b.Loop() {...}" are guaranteed +-// not to be optimized away. +-// Also, the local loop scaling for b.Loop ensures the benchmark function containing the loop will only +-// be executed once, i.e. for such construct: ++// A typical benchmark is structured like: + // +-// testing.Benchmark(func(b *testing.B) { +-// ...(setup) +-// for b.Loop() { +-// ...(benchmark logic) +-// } +-// ...(clean-up) ++// func Benchmark(b *testing.B) { ++// ... setup ... ++// for b.Loop() { ++// ... code to measure ... ++// } ++// ... cleanup ... + // } + // +-// The ...(setup) and ...(clean-up) logic will only be executed once. +-// Also benchtime=Nx (N>1) will result in exactly N executions instead of N+1 for b.N style loops. ++// Loop resets the benchmark timer the first time it is called in a benchmark, ++// so any setup performed prior to starting the benchmark loop does not count ++// toward the benchmark measurement. Likewise, when it returns false, it stops ++// the timer so cleanup code is not measured. ++// ++// The compiler never optimizes away calls to functions within the body of a ++// "for b.Loop() { ... }" loop. This prevents surprises that can otherwise occur ++// if the compiler determines that the result of a benchmarked function is ++// unused. The loop must be written in exactly this form, and this only applies ++// to calls syntactically between the curly braces of the loop. Optimizations ++// are performed as usual in any functions called by the loop. ++// ++// After Loop returns false, b.N contains the total number of iterations that ++// ran, so the benchmark may use b.N to compute other average metrics. ++// ++// Prior to the introduction of Loop, benchmarks were expected to contain an ++// explicit loop from 0 to b.N. Benchmarks should either use Loop or contain a ++// loop to b.N, but not both. Loop offers more automatic management of the ++// benchmark timer, and runs each benchmark function only once per measurement, ++// whereas b.N-based benchmarks must run the benchmark function (and any ++// associated setup and cleanup) several times. + func (b *B) Loop() bool { + if b.loopN != 0 && b.loopN < b.N { + b.loopN++ +diff --git a/src/testing/benchmark_test.go b/src/testing/benchmark_test.go +index 259b70ed4c..e2dd24c839 100644 +--- a/src/testing/benchmark_test.go ++++ b/src/testing/benchmark_test.go +@@ -7,6 +7,8 @@ package testing_test + import ( + "bytes" + "cmp" ++ "context" ++ "errors" + "runtime" + "slices" + "strings" +@@ -127,56 +129,32 @@ func TestRunParallelSkipNow(t *testing.T) { + }) + } + +-func TestBLoopHasResults(t *testing.T) { +- // Verify that b.N and the b.Loop() iteration count match. +- var nIterated int +- bRet := testing.Benchmark(func(b *testing.B) { +- i := 0 +- for b.Loop() { +- i++ +- } +- nIterated = i +- }) +- if nIterated == 0 { +- t.Fatalf("Iteration count zero") +- } +- if bRet.N != nIterated { +- t.Fatalf("Benchmark result N incorrect, got %d want %d", bRet.N, nIterated) +- } +- // We only need to check duration to make sure benchmark result is written. +- if bRet.T == 0 { +- t.Fatalf("Benchmark result duration unset") +- } +-} +- +-func ExampleB_Loop() { +- simpleFunc := func(i int) int { +- return i + 1 +- } +- n := 0 ++func TestBenchmarkContext(t *testing.T) { + testing.Benchmark(func(b *testing.B) { +- // Unlike "for i := range N {...}" style loops, this +- // setup logic will only be executed once, so simpleFunc +- // will always get argument 1. +- n++ +- // It behaves just like "for i := range N {...}", except with keeping +- // function call parameters and results alive. +- for b.Loop() { +- // This function call, if was in a normal loop, will be optimized away +- // completely, first by inlining, then by dead code elimination. +- // In a b.Loop loop, the compiler ensures that this function is not optimized away. +- simpleFunc(n) ++ ctx := b.Context() ++ if err := ctx.Err(); err != nil { ++ b.Fatalf("expected non-canceled context, got %v", err) + } +- // This clean-up will only be executed once, so after the benchmark, the user +- // will see n == 2. +- n++ +- // Use b.ReportMetric as usual just like what a user may do after +- // b.N loop. +- }) +- // We can expect n == 2 here. + +- // The return value of the above Benchmark could be used just like +- // a b.N loop benchmark as well. ++ var innerCtx context.Context ++ b.Run("inner", func(b *testing.B) { ++ innerCtx = b.Context() ++ if err := innerCtx.Err(); err != nil { ++ b.Fatalf("expected inner benchmark to not inherit canceled context, got %v", err) ++ } ++ }) ++ b.Run("inner2", func(b *testing.B) { ++ if !errors.Is(innerCtx.Err(), context.Canceled) { ++ t.Fatal("expected context of sibling benchmark to be canceled after its test function finished") ++ } ++ }) ++ ++ t.Cleanup(func() { ++ if !errors.Is(ctx.Err(), context.Canceled) { ++ t.Fatal("expected context canceled before cleanup") ++ } ++ }) ++ }) + } + + func ExampleB_RunParallel() { +@@ -219,7 +197,7 @@ func ExampleB_ReportMetric() { + // specific algorithm (in this case, sorting). + testing.Benchmark(func(b *testing.B) { + var compares int64 +- for i := 0; i < b.N; i++ { ++ for b.Loop() { + s := []int{5, 4, 3, 2, 1} + slices.SortFunc(s, func(a, b int) int { + compares++ +diff --git a/src/testing/example_loop_test.go b/src/testing/example_loop_test.go +new file mode 100644 +index 0000000000..eff8bab352 +--- /dev/null ++++ b/src/testing/example_loop_test.go +@@ -0,0 +1,48 @@ ++// Copyright 2024 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package testing_test ++ ++import ( ++ "math/rand/v2" ++ "testing" ++) ++ ++// ExBenchmark shows how to use b.Loop in a benchmark. ++// ++// (If this were a real benchmark, not an example, this would be named ++// BenchmarkSomething.) ++func ExBenchmark(b *testing.B) { ++ // Generate a large random slice to use as an input. ++ // Since this is done before the first call to b.Loop(), ++ // it doesn't count toward the benchmark time. ++ input := make([]int, 128<<10) ++ for i := range input { ++ input[i] = rand.Int() ++ } ++ ++ // Perform the benchmark. ++ for b.Loop() { ++ // Normally, the compiler would be allowed to optimize away the call ++ // to sum because it has no side effects and the result isn't used. ++ // However, inside a b.Loop loop, the compiler ensures function calls ++ // aren't optimized away. ++ sum(input) ++ } ++ ++ // Outside the loop, the timer is stopped, so we could perform ++ // cleanup if necessary without affecting the result. ++} ++ ++func sum(data []int) int { ++ total := 0 ++ for _, value := range data { ++ total += value ++ } ++ return total ++} ++ ++func ExampleB_Loop() { ++ testing.Benchmark(ExBenchmark) ++} +diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go +index b41a07f88e..dceb786ae2 100644 +--- a/src/testing/fuzz.go ++++ b/src/testing/fuzz.go +@@ -5,6 +5,7 @@ + package testing + + import ( ++ "context" + "errors" + "flag" + "fmt" +@@ -293,6 +294,8 @@ func (f *F) Fuzz(ff any) { + f.tstate.match.clearSubNames() + } + ++ ctx, cancelCtx := context.WithCancel(f.ctx) ++ + // Record the stack trace at the point of this call so that if the subtest + // function - which runs in a separate stack - is marked as a helper, we can + // continue walking the stack into the parent test. +@@ -300,13 +303,15 @@ func (f *F) Fuzz(ff any) { + n := runtime.Callers(2, pc[:]) + t := &T{ + common: common{ +- barrier: make(chan bool), +- signal: make(chan bool), +- name: testName, +- parent: &f.common, +- level: f.level + 1, +- creator: pc[:n], +- chatty: f.chatty, ++ barrier: make(chan bool), ++ signal: make(chan bool), ++ name: testName, ++ parent: &f.common, ++ level: f.level + 1, ++ creator: pc[:n], ++ chatty: f.chatty, ++ ctx: ctx, ++ cancelCtx: cancelCtx, + }, + tstate: f.tstate, + } +@@ -508,14 +513,17 @@ func runFuzzTests(deps testDeps, fuzzTests []InternalFuzzTarget, deadline time.T + continue + } + } ++ ctx, cancelCtx := context.WithCancel(context.Background()) + f := &F{ + common: common{ +- signal: make(chan bool), +- barrier: make(chan bool), +- name: testName, +- parent: &root, +- level: root.level + 1, +- chatty: root.chatty, ++ signal: make(chan bool), ++ barrier: make(chan bool), ++ name: testName, ++ parent: &root, ++ level: root.level + 1, ++ chatty: root.chatty, ++ ctx: ctx, ++ cancelCtx: cancelCtx, + }, + tstate: tstate, + fstate: fstate, +@@ -590,14 +598,17 @@ func runFuzzing(deps testDeps, fuzzTests []InternalFuzzTarget) (ok bool) { + return false + } + ++ ctx, cancelCtx := context.WithCancel(context.Background()) + f := &F{ + common: common{ +- signal: make(chan bool), +- barrier: nil, // T.Parallel has no effect when fuzzing. +- name: testName, +- parent: &root, +- level: root.level + 1, +- chatty: root.chatty, ++ signal: make(chan bool), ++ barrier: nil, // T.Parallel has no effect when fuzzing. ++ name: testName, ++ parent: &root, ++ level: root.level + 1, ++ chatty: root.chatty, ++ ctx: ctx, ++ cancelCtx: cancelCtx, + }, + fstate: fstate, + tstate: tstate, +diff --git a/src/testing/loop_test.go b/src/testing/loop_test.go +new file mode 100644 +index 0000000000..7a1a93fcee +--- /dev/null ++++ b/src/testing/loop_test.go +@@ -0,0 +1,57 @@ ++// Copyright 2024 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package testing ++ ++func TestBenchmarkBLoop(t *T) { ++ var initialStart highPrecisionTime ++ var firstStart highPrecisionTime ++ var lastStart highPrecisionTime ++ var runningEnd bool ++ runs := 0 ++ iters := 0 ++ finalBN := 0 ++ bRet := Benchmark(func(b *B) { ++ initialStart = b.start ++ runs++ ++ for b.Loop() { ++ if iters == 0 { ++ firstStart = b.start ++ } ++ lastStart = b.start ++ iters++ ++ } ++ finalBN = b.N ++ runningEnd = b.timerOn ++ }) ++ // Verify that a b.Loop benchmark is invoked just once. ++ if runs != 1 { ++ t.Errorf("want runs == 1, got %d", runs) ++ } ++ // Verify that at least one iteration ran. ++ if iters == 0 { ++ t.Fatalf("no iterations ran") ++ } ++ // Verify that b.N, bRet.N, and the b.Loop() iteration count match. ++ if finalBN != iters || bRet.N != iters { ++ t.Errorf("benchmark iterations mismatch: %d loop iterations, final b.N=%d, bRet.N=%d", iters, finalBN, bRet.N) ++ } ++ // Make sure the benchmark ran for an appropriate amount of time. ++ if bRet.T < benchTime.d { ++ t.Fatalf("benchmark ran for %s, want >= %s", bRet.T, benchTime.d) ++ } ++ // Verify that the timer is reset on the first loop, and then left alone. ++ if firstStart == initialStart { ++ t.Errorf("b.Loop did not reset the timer") ++ } ++ if lastStart != firstStart { ++ t.Errorf("timer was reset during iteration") ++ } ++ // Verify that it stopped the timer after the last loop. ++ if runningEnd { ++ t.Errorf("timer was still running after last iteration") ++ } ++} ++ ++// See also TestBenchmarkBLoop* in other files. +diff --git a/src/testing/synctest/context_example_test.go b/src/testing/synctest/context_example_test.go +new file mode 100644 +index 0000000000..5f7205e50e +--- /dev/null ++++ b/src/testing/synctest/context_example_test.go +@@ -0,0 +1,78 @@ ++// Copyright 2025 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build goexperiment.synctest ++ ++package synctest_test ++ ++import ( ++ "context" ++ "fmt" ++ "testing/synctest" ++ "time" ++) ++ ++// This example demonstrates testing the context.AfterFunc function. ++// ++// AfterFunc registers a function to execute in a new goroutine ++// after a context is canceled. ++// ++// The test verifies that the function is not run before the context is canceled, ++// and is run after the context is canceled. ++func Example_contextAfterFunc() { ++ synctest.Run(func() { ++ // Create a context.Context which can be canceled. ++ ctx, cancel := context.WithCancel(context.Background()) ++ ++ // context.AfterFunc registers a function to be called ++ // when a context is canceled. ++ afterFuncCalled := false ++ context.AfterFunc(ctx, func() { ++ afterFuncCalled = true ++ }) ++ ++ // The context has not been canceled, so the AfterFunc is not called. ++ synctest.Wait() ++ fmt.Printf("before context is canceled: afterFuncCalled=%v\n", afterFuncCalled) ++ ++ // Cancel the context and wait for the AfterFunc to finish executing. ++ // Verify that the AfterFunc ran. ++ cancel() ++ synctest.Wait() ++ fmt.Printf("after context is canceled: afterFuncCalled=%v\n", afterFuncCalled) ++ ++ // Output: ++ // before context is canceled: afterFuncCalled=false ++ // after context is canceled: afterFuncCalled=true ++ }) ++} ++ ++// This example demonstrates testing the context.WithTimeout function. ++// ++// WithTimeout creates a context which is canceled after a timeout. ++// ++// The test verifies that the context is not canceled before the timeout expires, ++// and is canceled after the timeout expires. ++func Example_contextWithTimeout() { ++ synctest.Run(func() { ++ // Create a context.Context which is canceled after a timeout. ++ const timeout = 5 * time.Second ++ ctx, cancel := context.WithTimeout(context.Background(), timeout) ++ defer cancel() ++ ++ // Wait just less than the timeout. ++ time.Sleep(timeout - time.Nanosecond) ++ synctest.Wait() ++ fmt.Printf("before timeout: ctx.Err() = %v\n", ctx.Err()) ++ ++ // Wait the rest of the way until the timeout. ++ time.Sleep(time.Nanosecond) ++ synctest.Wait() ++ fmt.Printf("after timeout: ctx.Err() = %v\n", ctx.Err()) ++ ++ // Output: ++ // before timeout: ctx.Err() = ++ // after timeout: ctx.Err() = context deadline exceeded ++ }) ++} +diff --git a/src/testing/testing.go b/src/testing/testing.go +index e353ceb741..be6391b0ab 100644 +--- a/src/testing/testing.go ++++ b/src/testing/testing.go +@@ -72,27 +72,24 @@ + // A sample benchmark function looks like this: + // + // func BenchmarkRandInt(b *testing.B) { +-// for range b.N { ++// for b.Loop() { + // rand.Int() + // } + // } + // +-// The benchmark function must run the target code b.N times. +-// It is called multiple times with b.N adjusted until the +-// benchmark function lasts long enough to be timed reliably. + // The output + // + // BenchmarkRandInt-8 68453040 17.8 ns/op + // +-// means that the loop ran 68453040 times at a speed of 17.8 ns per loop. ++// means that the body of the loop ran 68453040 times at a speed of 17.8 ns per loop. + // +-// If a benchmark needs some expensive setup before running, the timer +-// may be reset: ++// Only the body of the loop is timed, so benchmarks may do expensive ++// setup before calling b.Loop, which will not be counted toward the ++// benchmark measurement: + // + // func BenchmarkBigLen(b *testing.B) { + // big := NewBig() +-// b.ResetTimer() +-// for range b.N { ++// for b.Loop() { + // big.Len() + // } + // } +@@ -120,6 +117,37 @@ + // In particular, https://golang.org/x/perf/cmd/benchstat performs + // statistically robust A/B comparisons. + // ++// # b.N-style benchmarks ++// ++// Prior to the introduction of [B.Loop], benchmarks were written in a ++// different style using [B.N]. For example: ++// ++// func BenchmarkRandInt(b *testing.B) { ++// for range b.N { ++// rand.Int() ++// } ++// } ++// ++// In this style of benchmark, the benchmark function must run ++// the target code b.N times. The benchmark function is called ++// multiple times with b.N adjusted until the benchmark function ++// lasts long enough to be timed reliably. This also means any setup ++// done before the loop may be run several times. ++// ++// If a benchmark needs some expensive setup before running, the timer ++// should be explicitly reset: ++// ++// func BenchmarkBigLen(b *testing.B) { ++// big := NewBig() ++// b.ResetTimer() ++// for range b.N { ++// big.Len() ++// } ++// } ++// ++// New benchmarks should prefer using [B.Loop], which is more robust ++// and more efficient. ++// + // # Examples + // + // The package also runs and verifies example code. Example functions may +@@ -1357,10 +1385,10 @@ func (c *common) Chdir(dir string) { + } + + // Context returns a context that is canceled just before +-// [T.Cleanup]-registered functions are called. ++// Cleanup-registered functions are called. + // + // Cleanup functions can wait for any resources +-// that shut down on Context.Done before the test completes. ++// that shut down on Context.Done before the test or benchmark completes. + func (c *common) Context() context.Context { + c.checkFuzzFn("Context") + return c.ctx +diff --git a/src/unique/handle.go b/src/unique/handle.go +index 46f2da3ddc..520ab70f8c 100644 +--- a/src/unique/handle.go ++++ b/src/unique/handle.go +@@ -89,7 +89,7 @@ func Make[T comparable](value T) Handle[T] { + } + + var ( +- // uniqueMaps is an index of type-specific sync maps used for unique.Make. ++ // uniqueMaps is an index of type-specific concurrent maps used for unique.Make. + // + // The two-level map might seem odd at first since the HashTrieMap could have "any" + // as its key type, but the issue is escape analysis. We do not want to force lookups +diff --git a/src/weak/pointer.go b/src/weak/pointer.go +index fb10bc2d69..39c512e76d 100644 +--- a/src/weak/pointer.go ++++ b/src/weak/pointer.go +@@ -13,9 +13,9 @@ import ( + // Pointer is a weak pointer to a value of type T. + // + // Just like regular pointers, Pointer may reference any part of an +-// object, such as the field of a struct or an element of an array. ++// object, such as a field of a struct or an element of an array. + // Objects that are only pointed to by weak pointers are not considered +-// reachable and once the object becomes unreachable [Pointer.Value] ++// reachable, and once the object becomes unreachable, [Pointer.Value] + // may return nil. + // + // The primary use-cases for weak pointers are for implementing caches, +@@ -23,19 +23,19 @@ import ( + // the lifetimes of separate values (for example, through a map with weak + // keys). + // +-// Two Pointer values always compare equal if the pointers that they were +-// created from compare equal. This property is retained even after the ++// Two Pointer values always compare equal if the pointers from which they were ++// created compare equal. This property is retained even after the + // object referenced by the pointer used to create a weak reference is + // reclaimed. +-// If multiple weak pointers are made to different offsets within same object ++// If multiple weak pointers are made to different offsets within the same object + // (for example, pointers to different fields of the same struct), those pointers + // will not compare equal. + // If a weak pointer is created from an object that becomes unreachable, but is + // then resurrected due to a finalizer, that weak pointer will not compare equal +-// with weak pointers created after resurrection. ++// with weak pointers created after the resurrection. + // + // Calling [Make] with a nil pointer returns a weak pointer whose [Pointer.Value] +-// always returns nil. The zero value of a Pointer behaves as if it was created ++// always returns nil. The zero value of a Pointer behaves as if it were created + // by passing nil to [Make] and compares equal with such pointers. + // + // [Pointer.Value] is not guaranteed to eventually return nil. +@@ -52,7 +52,7 @@ import ( + // nil, even after an object is no longer referenced, the runtime is allowed to + // perform a space-saving optimization that batches objects together in a single + // allocation slot. The weak pointer for an unreferenced object in such an +-// allocation may never be called if it always exists in the same batch as a ++// allocation may never become nil if it always exists in the same batch as a + // referenced object. Typically, this batching only happens for tiny + // (on the order of 16 bytes or less) and pointer-free objects. + type Pointer[T any] struct { +@@ -78,6 +78,9 @@ func Make[T any](ptr *T) Pointer[T] { + // If a weak pointer points to an object with a finalizer, then Value will + // return nil as soon as the object's finalizer is queued for execution. + func (p Pointer[T]) Value() *T { ++ if p.u == nil { ++ return nil ++ } + return (*T)(runtime_makeStrongFromWeak(p.u)) + } + +diff --git a/src/weak/pointer_test.go b/src/weak/pointer_test.go +index 002b4130f0..e0ef30377e 100644 +--- a/src/weak/pointer_test.go ++++ b/src/weak/pointer_test.go +@@ -21,6 +21,15 @@ type T struct { + } + + func TestPointer(t *testing.T) { ++ var zero weak.Pointer[T] ++ if zero.Value() != nil { ++ t.Error("Value of zero value of weak.Pointer is not nil") ++ } ++ zeroNil := weak.Make[T](nil) ++ if zeroNil.Value() != nil { ++ t.Error("Value of weak.Make[T](nil) is not nil") ++ } ++ + bt := new(T) + wt := weak.Make(bt) + if st := wt.Value(); st != bt { +@@ -41,6 +50,12 @@ func TestPointer(t *testing.T) { + } + + func TestPointerEquality(t *testing.T) { ++ var zero weak.Pointer[T] ++ zeroNil := weak.Make[T](nil) ++ if zero != zeroNil { ++ t.Error("weak.Make[T](nil) != zero value of weak.Pointer[T]") ++ } ++ + bt := make([]*T, 10) + wt := make([]weak.Pointer[T], 10) + wo := make([]weak.Pointer[int], 10) diff --git a/fedora.go b/fedora.go index 81b28ba..3ff4d3e 100644 --- a/fedora.go +++ b/fedora.go @@ -1,5 +1,9 @@ +//go:build rpm_crashtraceback // +build rpm_crashtraceback +// Copyright 2017 The Fedora Project Contributors. All rights reserved. +// Use of this source code is governed by the MIT license. + package runtime func init() { diff --git a/golang.spec b/golang.spec index 439ccab..8f11e18 100644 --- a/golang.spec +++ b/golang.spec @@ -99,9 +99,9 @@ %endif # Comment out go_prerelease and go_patch as needed -%global go_api 1.23 -#global go_prerelease rc2 -%global go_patch 4 +%global go_api 1.24 +%global go_prerelease rc1 +#global go_patch 4 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} @@ -135,19 +135,19 @@ BuildRequires: pcre2-devel, glibc-static, perl-interpreter, procps-ng Provides: go = %{version}-%{release} # Bundled/Vendored provides generated by bundled-deps.sh based on the in tree module data -Provides: bundled(golang(github.com/google/pprof)) = 0.0.0.20240528025155.186aa0362fba -Provides: bundled(golang(github.com/ianlancetaylor/demangle)) = 0.0.0.20240312041847.bd984b5ce465 -Provides: bundled(golang(golang.org/x/arch)) = 0.8.0 -Provides: bundled(golang(golang.org/x/build)) = 0.0.0.20240603162849.5dfbda438323 -Provides: bundled(golang(golang.org/x/crypto)) = 0.23.1.0.20240603234054.0b431c7de36a -Provides: bundled(golang(golang.org/x/mod)) = 0.19.0 -Provides: bundled(golang(golang.org/x/net)) = 0.25.1.0.20240603202750.6249541f2a6c -Provides: bundled(golang(golang.org/x/sync)) = 0.7.0 -Provides: bundled(golang(golang.org/x/sys)) = 0.22.0 -Provides: bundled(golang(golang.org/x/telemetry)) = 0.0.0.20240828213427.40b6b7fe7147 -Provides: bundled(golang(golang.org/x/term)) = 0.20.0 -Provides: bundled(golang(golang.org/x/text)) = 0.16.0 -Provides: bundled(golang(golang.org/x/tools)) = 0.22.1.0.20240618181713.f2d2ebe43e72 +Provides: bundled(golang(github.com/google/pprof)) = 0.0.0.20241101162523.b92577c0c142 +Provides: bundled(golang(github.com/ianlancetaylor/demangle)) = 0.0.0.20240912202439.0a2b6291aafd +Provides: bundled(golang(golang.org/x/arch)) = 0.12.0 +Provides: bundled(golang(golang.org/x/build)) = 0.0.0.20241205234318.b850320af2a4 +Provides: bundled(golang(golang.org/x/crypto)) = 0.30.0 +Provides: bundled(golang(golang.org/x/mod)) = 0.22.0 +Provides: bundled(golang(golang.org/x/net)) = 0.32.1.0.20241206180132.552d8ac903a1 +Provides: bundled(golang(golang.org/x/sync)) = 0.10.0 +Provides: bundled(golang(golang.org/x/sys)) = 0.28.0 +Provides: bundled(golang(golang.org/x/telemetry)) = 0.0.0.20241204182053.c0ac0e154df3 +Provides: bundled(golang(golang.org/x/term)) = 0.27.0 +Provides: bundled(golang(golang.org/x/text)) = 0.21.0 +Provides: bundled(golang(golang.org/x/tools)) = 0.28.0 Provides: bundled(golang(rsc.io/markdown)) = 0.0.0.20240306144322.0bf8f97ee8ef Requires: %{name}-bin = %{version}-%{release} @@ -157,6 +157,10 @@ Requires: go-filesystem Patch1: 0001-Modify-go.env.patch Patch5: 0005-Skip-TestCrashDumpsAllThreads.patch Patch6: 0006-Default-to-ld.bfd-on-ARM64.patch +# This is a huge patch. At the time of the Fedora merge, there was no rc2 tag +# to include a significant amount of necessary changes so I generated a single patch +# git diff go1.24rc1..release-branch.go1.24 > combined_commits_2025-01-08.patch +Patch7: combined_commits_2025-01-08.patch # Having documentation separate was broken Obsoletes: %{name}-docs < 1.1-4 diff --git a/sources b/sources index 4c20feb..a426d66 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.23.4.src.tar.gz) = 5d1cce76b2cbdf628f86a1a8185a07f362becee053cb4270281520e77b36e3908faeaf5b2a6266e61dec9866dc1f3791f77e8dc1bf5f8beaf858c138d0e18c22 +SHA512 (go1.24rc1.src.tar.gz) = f37b24f9964a7f6580ca0ecb1c4d197d8053429753b1b559dae0d66041c7274a3981daae5dddf93677e23a20dcf5cbdc4b70fbc772df46a611f6a063af3d3d64 From f423a1395365258342626315f58b4c90dfeb8d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Wed, 15 Jan 2025 22:41:57 +0100 Subject: [PATCH 40/75] Add a patch to fix issue with gcc15 in x86 --- fix_cgo_panic-with-gcc15-in-368.patch | 25 +++++++++++++++++++++++++ golang.spec | 1 + 2 files changed, 26 insertions(+) create mode 100644 fix_cgo_panic-with-gcc15-in-368.patch diff --git a/fix_cgo_panic-with-gcc15-in-368.patch b/fix_cgo_panic-with-gcc15-in-368.patch new file mode 100644 index 0000000..372af28 --- /dev/null +++ b/fix_cgo_panic-with-gcc15-in-368.patch @@ -0,0 +1,25 @@ +From 5f566346b70403891cfc52d0c807d72335691708 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= +Date: Wed, 15 Jan 2025 21:45:33 +0100 +Subject: [PATCH] Fix _cgo_panic with gcc15 in 368 + +--- + src/cmd/link/internal/x86/asm.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go +index d535e5fb4d..c4253a8c08 100644 +--- a/src/cmd/link/internal/x86/asm.go ++++ b/src/cmd/link/internal/x86/asm.go +@@ -184,7 +184,7 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade + return true + } + +- if r.Off() >= 2 && sData[r.Off()-2] == 0xff && sData[r.Off()-1] == 0xb3 { ++ if r.Off() >= 2 && sData[r.Off()-2] == 0xff && sData[r.Off()-1] >= 0xb0 && sData[r.Off()-1] <= 0xb7 { + su.MakeWritable() + // turn PUSHL of GOT entry into PUSHL of symbol itself. + // use unnecessary SS prefix to keep instruction same length. +-- +2.47.1 + diff --git a/golang.spec b/golang.spec index 8f11e18..3623fbc 100644 --- a/golang.spec +++ b/golang.spec @@ -161,6 +161,7 @@ Patch6: 0006-Default-to-ld.bfd-on-ARM64.patch # to include a significant amount of necessary changes so I generated a single patch # git diff go1.24rc1..release-branch.go1.24 > combined_commits_2025-01-08.patch Patch7: combined_commits_2025-01-08.patch +Patch8: fix_cgo_panic-with-gcc15-in-368.patch # Having documentation separate was broken Obsoletes: %{name}-docs < 1.1-4 From 31bbb1cda04b702950af4c43cf90cd1eed0964c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Wed, 15 Jan 2025 23:11:26 +0100 Subject: [PATCH 41/75] Add reference to a patch I realized that I didn't document correctly the fix_cgo_panic-with-gcc15-in-368.patch patch and it's a complex one. I included the gcc issue related to the solution: https://gcc.gnu.org/PR118497 --- golang.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/golang.spec b/golang.spec index 3623fbc..bccc07f 100644 --- a/golang.spec +++ b/golang.spec @@ -161,7 +161,8 @@ Patch6: 0006-Default-to-ld.bfd-on-ARM64.patch # to include a significant amount of necessary changes so I generated a single patch # git diff go1.24rc1..release-branch.go1.24 > combined_commits_2025-01-08.patch Patch7: combined_commits_2025-01-08.patch -Patch8: fix_cgo_panic-with-gcc15-in-368.patch +# Related to https://gcc.gnu.org/PR118497 +Patch8: fix_cgo_panic-with-gcc15-in-368.patch # Having documentation separate was broken Obsoletes: %{name}-docs < 1.1-4 From 5b44ac9a9dd7f6c56fc76e0fec73033376cf13bc Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 16 Jan 2025 23:10:27 +0000 Subject: [PATCH 42/75] Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild From d60b1a1b18eb11dd89d25fcc1111f7f402a9e6fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Fri, 17 Jan 2025 13:35:52 +0100 Subject: [PATCH 43/75] Update to go1.24rc2 Remove combined_commits_2025-01-08.patch --- .gitignore | 1 + combined_commits_2025-01-08.patch | 10002 ---------------------------- golang.spec | 6 +- sources | 2 +- 4 files changed, 3 insertions(+), 10008 deletions(-) delete mode 100644 combined_commits_2025-01-08.patch diff --git a/.gitignore b/.gitignore index f211ef9..5541ed2 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,4 @@ /go1.23.3.src.tar.gz /go1.23.4.src.tar.gz /go1.24rc1.src.tar.gz +/go1.24rc2.src.tar.gz diff --git a/combined_commits_2025-01-08.patch b/combined_commits_2025-01-08.patch deleted file mode 100644 index 1c05e69..0000000 --- a/combined_commits_2025-01-08.patch +++ /dev/null @@ -1,10002 +0,0 @@ -diff --git a/api/go1.24.txt b/api/go1.24.txt -index 795a70e354..05e2006e07 100644 ---- a/api/go1.24.txt -+++ b/api/go1.24.txt -@@ -106,16 +106,6 @@ pkg debug/elf, const VER_FLG_INFO = 4 #63952 - pkg debug/elf, const VER_FLG_INFO DynamicVersionFlag #63952 - pkg debug/elf, const VER_FLG_WEAK = 2 #63952 - pkg debug/elf, const VER_FLG_WEAK DynamicVersionFlag #63952 --pkg debug/elf, const VersionScopeGlobal = 2 #63952 --pkg debug/elf, const VersionScopeGlobal SymbolVersionScope #63952 --pkg debug/elf, const VersionScopeHidden = 4 #63952 --pkg debug/elf, const VersionScopeHidden SymbolVersionScope #63952 --pkg debug/elf, const VersionScopeLocal = 1 #63952 --pkg debug/elf, const VersionScopeLocal SymbolVersionScope #63952 --pkg debug/elf, const VersionScopeNone = 0 #63952 --pkg debug/elf, const VersionScopeNone SymbolVersionScope #63952 --pkg debug/elf, const VersionScopeSpecific = 3 #63952 --pkg debug/elf, const VersionScopeSpecific SymbolVersionScope #63952 - pkg debug/elf, method (*File) DynamicVersionNeeds() ([]DynamicVersionNeed, error) #63952 - pkg debug/elf, method (*File) DynamicVersions() ([]DynamicVersion, error) #63952 - pkg debug/elf, type DynamicVersion struct #63952 -@@ -131,9 +121,11 @@ pkg debug/elf, type DynamicVersionFlag uint16 #63952 - pkg debug/elf, type DynamicVersionNeed struct #63952 - pkg debug/elf, type DynamicVersionNeed struct, Name string #63952 - pkg debug/elf, type DynamicVersionNeed struct, Needs []DynamicVersionDep #63952 --pkg debug/elf, type Symbol struct, VersionScope SymbolVersionScope #63952 --pkg debug/elf, type Symbol struct, VersionIndex int16 #63952 --pkg debug/elf, type SymbolVersionScope uint8 #63952 -+pkg debug/elf, type Symbol struct, HasVersion bool #63952 -+pkg debug/elf, type Symbol struct, VersionIndex VersionIndex #63952 -+pkg debug/elf, method (VersionIndex) Index() uint16 #63952 -+pkg debug/elf, method (VersionIndex) IsHidden() bool #63952 -+pkg debug/elf, type VersionIndex uint16 #63952 - pkg encoding, type BinaryAppender interface { AppendBinary } #62384 - pkg encoding, type BinaryAppender interface, AppendBinary([]uint8) ([]uint8, error) #62384 - pkg encoding, type TextAppender interface { AppendText } #62384 -diff --git a/doc/go_spec.html b/doc/go_spec.html -index 31bea3713a..ab90c420fd 100644 ---- a/doc/go_spec.html -+++ b/doc/go_spec.html -@@ -1,6 +1,6 @@ - - -@@ -798,7 +798,6 @@ If a variable has not yet been assigned a value, its value is the - zero value for its type. - Types
- --@@ -810,12 +809,12 @@ from existing types. -
- ---Type = TypeName [ TypeArgs ] | TypeLit | "(" Type ")" . --TypeName = identifier | QualifiedIdent . --TypeArgs = "[" TypeList [ "," ] "]" . --TypeList = Type { "," Type } . --TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | -- SliceType | MapType | ChannelType . -+Type = TypeName [ TypeArgs ] | TypeLit | "(" Type ")" . -+TypeName = identifier | QualifiedIdent . -+TypeArgs = "[" TypeList [ "," ] "]" . -+TypeList = Type { "," Type } . -+TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | -+ SliceType | MapType | ChannelType . -- --@@ -1200,7 +1199,7 @@ type ( -
- A pointer type denotes the set of all pointers to variables of a given - type, called the base type of the pointer. --The value of an uninitialized pointer is
- -nil. -+The value of an uninitialized pointer isnil. --@@ -1216,18 +1215,18 @@ BaseType = Type . -Function types
- ---A function type denotes the set of all functions with the same parameter --and result types. The value of an uninitialized variable of function type --is
- -nil. -+A function type denotes the set of all functions with the same parameter and result types. -+The value of an uninitialized variable of function -+type isnil. ---FunctionType = "func" Signature . --Signature = Parameters [ Result ] . --Result = Parameters | Type . --Parameters = "(" [ ParameterList [ "," ] ] ")" . --ParameterList = ParameterDecl { "," ParameterDecl } . --ParameterDecl = [ IdentifierList ] [ "..." ] Type . -+FunctionType = "func" Signature . -+Signature = Parameters [ Result ] . -+Result = Parameters | Type . -+Parameters = "(" [ ParameterList [ "," ] ] ")" . -+ParameterList = ParameterDecl { "," ParameterDecl } . -+ParameterDecl = [ IdentifierList ] [ "..." ] Type . -- --@@ -1267,7 +1266,8 @@ An interface type defines a type set. - A variable of interface type can store a value of any type that is in the type - set of the interface. Such a type is said to - implement the interface. --The value of an uninitialized variable of interface type is
- -nil. -+The value of an uninitialized variable of -+interface type isnil. --@@ -1630,12 +1630,12 @@ implements the interface. - A map is an unordered group of elements of one type, called the - element type, indexed by a set of unique keys of another type, - called the key type. --The value of an uninitialized map isnil. -+The value of an uninitialized map isnil. - - ---MapType = "map" "[" KeyType "]" ElementType . --KeyType = Type . -+MapType = "map" "[" KeyType "]" ElementType . -+KeyType = Type . -- --@@ -1693,7 +1693,7 @@ to communicate by - sending and - receiving - values of a specified element type. --The value of an uninitialized channel is
- -nil. -+The value of an uninitialized channel isnil. --@@ -1772,6 +1772,57 @@ received in the order sent. - -Properties of types and values
- -+Representation of values
-+ -+-+Values of predeclared types (see below for the interfaces
-+ -+any-+anderror), arrays, and structs are self-contained: -+Each such value contains a complete copy of all its data, -+and variables of such types store the entire value. -+For instance, an array variable provides the storage (the variables) -+for all elements of the array. -+The respective zero values are specific to the -+value's types; they are nevernil. -+-+Non-nil pointer, function, slice, map, and channel values contain references -+to underlying data which may be shared by multiple values: -+
-+ -+
-+An interface value may be self-contained or contain references to underlying data
-+depending on the interface's dynamic type.
-+The predeclared identifier nil is the zero value for types whose values
-+can contain references.
-+
-+When multiple values share underlying data, changing one value may change another. -+For instance, changing an element of a slice will change -+that element in the underlying array for all slices that share the array. -+
-+ --@@ -2176,7 +2227,7 @@ within matching brace brackets. -
- -
--Block = "{" StatementList "}" .
-+Block = "{" StatementList "}" .
- StatementList = { Statement ";" } .
-
-
-@@ -2233,8 +2284,8 @@ and like the blank identifier it does not introduce a new binding.
-
-
- --Declaration = ConstDecl | TypeDecl | VarDecl . --TopLevelDecl = Declaration | FunctionDecl | MethodDecl . -+Declaration = ConstDecl | TypeDecl | VarDecl . -+TopLevelDecl = Declaration | FunctionDecl | MethodDecl . -- -
-@@ -2679,9 +2730,9 @@ in square brackets rather than parentheses -
- -
--TypeParameters = "[" TypeParamList [ "," ] "]" .
--TypeParamList = TypeParamDecl { "," TypeParamDecl } .
--TypeParamDecl = IdentifierList TypeConstraint .
-+TypeParameters = "[" TypeParamList [ "," ] "]" .
-+TypeParamList = TypeParamDecl { "," TypeParamDecl } .
-+TypeParamDecl = IdentifierList TypeConstraint .
-
-
- -@@ -2819,7 +2870,7 @@ values or variables, or components of other, non-interface types. - -
- A type argument T satisfies a type constraint C
--if T is an element of the type set defined by C; i.e.,
-+if T is an element of the type set defined by C; in other words,
- if T implements C.
- As an exception, a strictly comparable
- type constraint may also be satisfied by a comparable
-@@ -2869,8 +2920,8 @@ binds corresponding identifiers to them, and gives each a type and an initial va
-
--VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
--VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
-+VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
-+VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
-
-
- -@@ -2899,7 +2950,7 @@ initialization value in the assignment. - If that value is an untyped constant, it is first implicitly - converted to its default type; - if it is an untyped boolean value, it is first implicitly converted to typebool. --The predeclared valuenilcannot be used to initialize a variable -+The predeclared identifiernilcannot be used to initialize a variable - with no explicit type. - - -@@ -3210,15 +3261,15 @@ Each element may optionally be preceded by a corresponding key. - - ---CompositeLit = LiteralType LiteralValue . --LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | -- SliceType | MapType | TypeName [ TypeArgs ] . --LiteralValue = "{" [ ElementList [ "," ] ] "}" . --ElementList = KeyedElement { "," KeyedElement } . --KeyedElement = [ Key ":" ] Element . --Key = FieldName | Expression | LiteralValue . --FieldName = identifier . --Element = Expression | LiteralValue . -+CompositeLit = LiteralType LiteralValue . -+LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | -+ SliceType | MapType | TypeName [ TypeArgs ] . -+LiteralValue = "{" [ ElementList [ "," ] ] "}" . -+ElementList = KeyedElement { "," KeyedElement } . -+KeyedElement = [ Key ":" ] Element . -+Key = FieldName | Expression | LiteralValue . -+FieldName = identifier . -+Element = Expression | LiteralValue . -- --@@ -3450,22 +3501,21 @@ Primary expressions are the operands for unary and binary expressions. -
- ---PrimaryExpr = -- Operand | -- Conversion | -- MethodExpr | -- PrimaryExpr Selector | -- PrimaryExpr Index | -- PrimaryExpr Slice | -- PrimaryExpr TypeAssertion | -- PrimaryExpr Arguments . -+PrimaryExpr = Operand | -+ Conversion | -+ MethodExpr | -+ PrimaryExpr Selector | -+ PrimaryExpr Index | -+ PrimaryExpr Slice | -+ PrimaryExpr TypeAssertion | -+ PrimaryExpr Arguments . - --Selector = "." identifier . --Index = "[" Expression [ "," ] "]" . --Slice = "[" [ Expression ] ":" [ Expression ] "]" | -- "[" [ Expression ] ":" Expression ":" Expression "]" . --TypeAssertion = "." "(" Type ")" . --Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" . -+Selector = "." identifier . -+Index = "[" Expression [ "," ] "]" . -+Slice = "[" [ Expression ] ":" [ Expression ] "]" | -+ "[" [ Expression ] ":" Expression ":" Expression "]" . -+TypeAssertion = "." "(" Type ")" . -+Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" . -- - -@@ -3638,8 +3688,8 @@ argument that is the receiver of the method. - - ---MethodExpr = ReceiverType "." MethodName . --ReceiverType = Type . -+MethodExpr = ReceiverType "." MethodName . -+ReceiverType = Type . -- --@@ -4230,8 +4280,7 @@ calls
fwith argumentsa1, a2, … an. - Except for one special case, arguments must be single-valued expressions - assignable to the parameter types of -Fand are evaluated before the function is called. --The type of the expression is the result type --ofF. -+The type of the expression is the result type ofF. - A method invocation is similar but the method itself - is specified as a selector upon a value of the receiver type for - the method. -@@ -4252,9 +4301,14 @@ or used as a function value. -- In a function call, the function value and arguments are evaluated in - the usual order. --After they are evaluated, the parameters of the call are passed by value to the function -+After they are evaluated, new storage is allocated for the function's -+variables, which includes its parameters -+and results. -+Then, the arguments of the call are passed to the function, -+which means that they are assigned -+to their corresponding function parameters, - and the called function begins execution. --The return parameters of the function are passed by value -+The return parameters of the function are passed - back to the caller when the function returns. -
- -@@ -4268,9 +4322,9 @@ As a special case, if the return values of a function or method -gare equal in number and individually - assignable to the parameters of another function or method -f, then the callf(g(parameters_of_g))--will invokefafter binding the return values of --gto the parameters offin order. The call --offmust contain no parameters other than the call ofg, -+will invokefafter passing the return values of -+gto the parameters offin order. -+The call offmust contain no parameters other than the call ofg, - andgmust have at least one return value. - Iffhas a final...parameter, it is - assigned the return values ofgthat remain after -@@ -4316,7 +4370,7 @@ Iffis variadic with a final - parameterpof type...T, then withinf- the type ofpis equivalent to type[]T. - Iffis invoked with no actual arguments forp, --the value passed topisnil. -+the value passed topisnil. - Otherwise, the value passed is a new slice - of type[]Twith a new underlying array whose successive elements - are the actual arguments, which all must be assignable -@@ -5632,6 +5686,8 @@ myString([]myRune{0x1f30e}) // "\U0001f30e" == "🌎" -
- []byte("hellø") // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
-@@ -5647,6 +5703,8 @@ bytes("hellø") // []byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'}
-
- []rune(myString("白鵬翔")) // []rune{0x767d, 0x9d6c, 0x7fd4}
-@@ -5848,7 +5906,7 @@ Otherwise, when evaluating the operands of an
- expression, assignment, or
- return statement,
- all function calls, method calls,
--receive operations,
-+receive operations,
- and binary logical operations
- are evaluated in lexical left-to-right order.
-
-@@ -5916,11 +5974,10 @@ Statements control execution.
-
-
-
--Statement =
-- Declaration | LabeledStmt | SimpleStmt |
-- GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
-- FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
-- DeferStmt .
-+Statement = Declaration | LabeledStmt | SimpleStmt |
-+ GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
-+ FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
-+ DeferStmt .
-
- SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
-
-@@ -6132,7 +6189,7 @@ matching number of variables.
-
- Assignment = ExpressionList assign_op ExpressionList .
-
--assign_op = [ add_op | mul_op ] "=" .
-+assign_op = [ add_op | mul_op ] "=" .
-
-
-
-@@ -6261,6 +6318,26 @@ to the type of the operand to which it is assigned, with the following special c
-
-+When a value is assigned to a variable, only the data that is stored in the variable -+is replaced. If the value contains a reference, -+the assignment copies the reference but does not make a copy of the referenced data -+(such as the underlying array of a slice). -+
-+ -+
-+var s1 = []int{1, 2, 3}
-+var s2 = s1 // s2 stores the slice descriptor of s1
-+s1 = s1[:1] // s1's length is 1 but it still shares its underlying array with s2
-+s2[0] = 42 // setting s2[0] changes s1[0] as well
-+fmt.Println(s1, s2) // prints [42] [42 2 3]
-+
-+var m1 = make(map[string]int)
-+var m2 = m1 // m2 stores the map descriptor of m1
-+m1["foo"] = 42 // setting m1["foo"] changes m2["foo"] as well
-+fmt.Println(m2["foo"]) // prints 42
-+
-+
- -@@ -6548,7 +6625,7 @@ The iteration may be controlled by a single condition, a "for" clause, or a "ran -
- ---ForStmt = "for" [ Condition | ForClause | RangeClause ] Block . -+ForStmt = "for" [ Condition | ForClause | RangeClause ] Block . - Condition = Expression . -- -@@ -6580,8 +6657,8 @@ an increment or decrement statement. The init statement may be a - -
- ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] . --InitStmt = SimpleStmt . --PostStmt = SimpleStmt . -+InitStmt = SimpleStmt . -+PostStmt = SimpleStmt . -- -
-@@ -7909,7 +7986,7 @@ types, variables, and constants. - - ---SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } . -+SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } . -- -Package clause
-@@ -7920,8 +7997,8 @@ to which the file belongs. - - ---PackageClause = "package" PackageName . --PackageName = identifier . -+PackageClause = "package" PackageName . -+PackageName = identifier . -- --@@ -7950,9 +8027,9 @@ that specifies the package to be imported. -
- ---ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) . --ImportSpec = [ "." | PackageName ] ImportPath . --ImportPath = string_lit . -+ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) . -+ImportSpec = [ "." | PackageName ] ImportPath . -+ImportPath = string_lit . -- --diff --git a/doc/initial/1-intro.md b/doc/initial/1-intro.md -index 8c9948ddf6..84ffee855a 100644 ---- a/doc/initial/1-intro.md -+++ b/doc/initial/1-intro.md -@@ -1,9 +1,3 @@ -- -- - -diff --git a/src/builtin/builtin.go b/src/builtin/builtin.go -index af01aea5dd..afa2a10f90 100644 ---- a/src/builtin/builtin.go -+++ b/src/builtin/builtin.go -@@ -162,12 +162,12 @@ func delete(m map[Type]Type1, key Type) - - // The len built-in function returns the length of v, according to its type: - // --// Array: the number of elements in v. --// Pointer to array: the number of elements in *v (even if v is nil). --// Slice, or map: the number of elements in v; if v is nil, len(v) is zero. --// String: the number of bytes in v. --// Channel: the number of elements queued (unread) in the channel buffer; --// if v is nil, len(v) is zero. -+// - Array: the number of elements in v. -+// - Pointer to array: the number of elements in *v (even if v is nil). -+// - Slice, or map: the number of elements in v; if v is nil, len(v) is zero. -+// - String: the number of bytes in v. -+// - Channel: the number of elements queued (unread) in the channel buffer; -+// if v is nil, len(v) is zero. - // - // For some arguments, such as a string literal or a simple array expression, the - // result can be a constant. See the Go language specification's "Length and -@@ -176,12 +176,12 @@ func len(v Type) int - - // The cap built-in function returns the capacity of v, according to its type: - // --// Array: the number of elements in v (same as len(v)). --// Pointer to array: the number of elements in *v (same as len(v)). --// Slice: the maximum length the slice can reach when resliced; --// if v is nil, cap(v) is zero. --// Channel: the channel buffer capacity, in units of elements; --// if v is nil, cap(v) is zero. -+// - Array: the number of elements in v (same as len(v)). -+// - Pointer to array: the number of elements in *v (same as len(v)). -+// - Slice: the maximum length the slice can reach when resliced; -+// if v is nil, cap(v) is zero. -+// - Channel: the channel buffer capacity, in units of elements; -+// if v is nil, cap(v) is zero. - // - // For some arguments, such as a simple array expression, the result can be a - // constant. See the Go language specification's "Length and capacity" section for -@@ -194,18 +194,18 @@ func cap(v Type) int - // argument, not a pointer to it. The specification of the result depends on - // the type: - // --// Slice: The size specifies the length. The capacity of the slice is --// equal to its length. A second integer argument may be provided to --// specify a different capacity; it must be no smaller than the --// length. For example, make([]int, 0, 10) allocates an underlying array --// of size 10 and returns a slice of length 0 and capacity 10 that is --// backed by this underlying array. --// Map: An empty map is allocated with enough space to hold the --// specified number of elements. The size may be omitted, in which case --// a small starting size is allocated. --// Channel: The channel's buffer is initialized with the specified --// buffer capacity. If zero, or the size is omitted, the channel is --// unbuffered. -+// - Slice: The size specifies the length. The capacity of the slice is -+// equal to its length. A second integer argument may be provided to -+// specify a different capacity; it must be no smaller than the -+// length. For example, make([]int, 0, 10) allocates an underlying array -+// of size 10 and returns a slice of length 0 and capacity 10 that is -+// backed by this underlying array. -+// - Map: An empty map is allocated with enough space to hold the -+// specified number of elements. The size may be omitted, in which case -+// a small starting size is allocated. -+// - Channel: The channel's buffer is initialized with the specified -+// buffer capacity. If zero, or the size is omitted, the channel is -+// unbuffered. - func make(t Type, size ...IntegerType) Type - - // The max built-in function returns the largest value of a fixed number of -diff --git a/src/bytes/iter.go b/src/bytes/iter.go -index 1cf13a94ec..9890a478a8 100644 ---- a/src/bytes/iter.go -+++ b/src/bytes/iter.go -@@ -68,7 +68,7 @@ func splitSeq(s, sep []byte, sepSave int) iter.Seq[[]byte] { - } - - // SplitSeq returns an iterator over all substrings of s separated by sep. --// The iterator yields the same strings that would be returned by Split(s, sep), -+// The iterator yields the same strings that would be returned by [Split](s, sep), - // but without constructing the slice. - // It returns a single-use iterator. - func SplitSeq(s, sep []byte) iter.Seq[[]byte] { -@@ -76,7 +76,7 @@ func SplitSeq(s, sep []byte) iter.Seq[[]byte] { - } - - // SplitAfterSeq returns an iterator over substrings of s split after each instance of sep. --// The iterator yields the same strings that would be returned by SplitAfter(s, sep), -+// The iterator yields the same strings that would be returned by [SplitAfter](s, sep), - // but without constructing the slice. - // It returns a single-use iterator. - func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] { -@@ -84,8 +84,8 @@ func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] { - } - - // FieldsSeq returns an iterator over substrings of s split around runs of --// whitespace characters, as defined by unicode.IsSpace. --// The iterator yields the same strings that would be returned by Fields(s), -+// whitespace characters, as defined by [unicode.IsSpace]. -+// The iterator yields the same strings that would be returned by [Fields](s), - // but without constructing the slice. - func FieldsSeq(s []byte) iter.Seq[[]byte] { - return func(yield func([]byte) bool) { -@@ -118,7 +118,7 @@ func FieldsSeq(s []byte) iter.Seq[[]byte] { - - // FieldsFuncSeq returns an iterator over substrings of s split around runs of - // Unicode code points satisfying f(c). --// The iterator yields the same strings that would be returned by FieldsFunc(s), -+// The iterator yields the same strings that would be returned by [FieldsFunc](s), - // but without constructing the slice. - func FieldsFuncSeq(s []byte, f func(rune) bool) iter.Seq[[]byte] { - return func(yield func([]byte) bool) { -diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go -index f45df3f86a..49abb857ad 100644 ---- a/src/cmd/compile/doc.go -+++ b/src/cmd/compile/doc.go -@@ -15,7 +15,7 @@ the package and about types used by symbols imported by the package from - other packages. It is therefore not necessary when compiling client C of - package P to read the files of P's dependencies, only the compiled output of P. - --Command Line -+# Command Line - - Usage: - -@@ -150,14 +150,21 @@ Flags to debug the compiler itself: - -w - Debug type checking. - --Compiler Directives -+# Compiler Directives - - The compiler accepts directives in the form of comments. --To distinguish them from non-directive comments, directives --require no space between the comment opening and the name of the directive. However, since --they are comments, tools unaware of the directive convention or of a particular -+Each directive must be placed its own line, with only leading spaces and tabs -+allowed before the comment, and there must be no space between the comment -+opening and the name of the directive, to distinguish it from a regular comment. -+Tools unaware of the directive convention or of a particular - directive can skip over a directive like any other comment. -+ -+Other than the line directive, which is a historical special case; -+all other compiler directives are of the form -+//go:name, indicating that they are defined by the Go toolchain. - */ -+// # Line Directives -+// - // Line directives come in several forms: - // - // //line :line -@@ -197,12 +204,9 @@ directive can skip over a directive like any other comment. - // Line directives typically appear in machine-generated code, so that compilers and debuggers - // will report positions in the original input to the generator. - /* --The line directive is a historical special case; all other directives are of the form --//go:name, indicating that they are defined by the Go toolchain. --Each directive must be placed its own line, with only leading spaces and tabs --allowed before the comment. --Each directive applies to the Go code that immediately follows it, --which typically must be a declaration. -+# Function Directives -+ -+A function directive applies to the Go function that immediately follows it. - - //go:noescape - -@@ -245,6 +249,8 @@ It specifies that the function must omit its usual stack overflow check. - This is most commonly used by low-level runtime code invoked - at times when it is unsafe for the calling goroutine to be preempted. - -+# Linkname Directive -+ - //go:linkname localname [importpath.name] - - The //go:linkname directive conventionally precedes the var or func -@@ -295,17 +301,34 @@ The declaration of lower.f may also have a linkname directive with a - single argument, f. This is optional, but helps alert the reader that - the function is accessed from outside the package. - -+# WebAssembly Directives -+ - //go:wasmimport importmodule importname - - The //go:wasmimport directive is wasm-only and must be followed by a --function declaration. -+function declaration with no body. - It specifies that the function is provided by a wasm module identified --by ``importmodule`` and ``importname``. -+by ``importmodule'' and ``importname''. For example, - - //go:wasmimport a_module f - func g() - --The types of parameters and return values to the Go function are translated to -+causes g to refer to the WebAssembly function f from module a_module. -+ -+ //go:wasmexport exportname -+ -+The //go:wasmexport directive is wasm-only and must be followed by a -+function definition. -+It specifies that the function is exported to the wasm host as ``exportname''. -+For example, -+ -+ //go:wasmexport h -+ func hWasm() { ... } -+ -+make Go function hWasm available outside this WebAssembly module as h. -+ -+For both go:wasmimport and go:wasmexport, -+the types of parameters and return values to the Go function are translated to - Wasm according to the following table: - - Go types Wasm types -@@ -318,24 +341,12 @@ Wasm according to the following table: - pointer i32 (more restrictions below) - string (i32, i32) (only permitted as a parameters, not a result) - -+Any other parameter types are disallowed by the compiler. -+ - For a pointer type, its element type must be a bool, int8, uint8, int16, uint16, - int32, uint32, int64, uint64, float32, float64, an array whose element type is - a permitted pointer element type, or a struct, which, if non-empty, embeds --structs.HostLayout, and contains only fields whose types are permitted pointer -+[structs.HostLayout], and contains only fields whose types are permitted pointer - element types. -- --Any other parameter types are disallowed by the compiler. -- -- //go:wasmexport exportname -- --The //go:wasmexport directive is wasm-only and must be followed by a --function definition. --It specifies that the function is exported to the wasm host as ``exportname``. -- -- //go:wasmexport f -- func g() -- --The types of parameters and return values to the Go function are permitted and --translated to Wasm in the same way as //go:wasmimport functions. - */ - package main -diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go -index dc9b508c01..edd1ffb0c9 100644 ---- a/src/cmd/compile/internal/ssagen/ssa.go -+++ b/src/cmd/compile/internal/ssagen/ssa.go -@@ -5452,12 +5452,15 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value { - if n.X.Type().IsChan() && n.Op() == ir.OCAP { - s.Fatalf("cannot inline cap(chan)") // must use runtime.chancap now - } -+ if n.X.Type().IsMap() && n.Op() == ir.OCAP { -+ s.Fatalf("cannot inline cap(map)") // cap(map) does not exist -+ } - // if n == nil { - // return 0 - // } else { -- // // len -- // return *((*int)n) -- // // cap -+ // // len, the actual loadType depends -+ // return int(*((*loadType)n)) -+ // // cap (chan only, not used for now) - // return *(((*int)n)+1) - // } - lenType := n.Type() -@@ -5485,7 +5488,9 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value { - case ir.OLEN: - if buildcfg.Experiment.SwissMap && n.X.Type().IsMap() { - // length is stored in the first word. -- s.vars[n] = s.load(lenType, x) -+ loadType := reflectdata.SwissMapType().Field(0).Type // uint64 -+ load := s.load(loadType, x) -+ s.vars[n] = s.conv(nil, load, loadType, lenType) // integer conversion doesn't need Node - } else { - // length is stored in the first word for map/chan - s.vars[n] = s.load(lenType, x) -diff --git a/src/cmd/compile/internal/syntax/testdata/issue70974.go b/src/cmd/compile/internal/syntax/testdata/issue70974.go -new file mode 100644 -index 0000000000..ebc69eda95 ---- /dev/null -+++ b/src/cmd/compile/internal/syntax/testdata/issue70974.go -@@ -0,0 +1,17 @@ -+// Copyright 2025 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package p -+ -+func _() { -+M: -+L: -+ for range 0 { -+ break L -+ break /* ERROR invalid break label M */ M -+ } -+ for range 0 { -+ break /* ERROR invalid break label L */ L -+ } -+} -diff --git a/src/cmd/compile/internal/types2/README.md b/src/cmd/compile/internal/types2/README.md -index 3d70cdbcf4..73253b4920 100644 ---- a/src/cmd/compile/internal/types2/README.md -+++ b/src/cmd/compile/internal/types2/README.md -@@ -56,7 +56,7 @@ The tests are in: - Tests are .go files annotated with `/* ERROR "msg" */` or `/* ERRORx "msg" */` - comments (or the respective line comment form). - For each such error comment, typechecking the respective file is expected to --report an error at the position of the syntactic token _immediately preceeding_ -+report an error at the position of the syntactic token _immediately preceding_ - the comment. - For `ERROR`, the `"msg"` string must be a substring of the error message - reported by the typechecker; -diff --git a/src/cmd/compile/internal/types2/api.go b/src/cmd/compile/internal/types2/api.go -index 74c549076d..49cc0e54ec 100644 ---- a/src/cmd/compile/internal/types2/api.go -+++ b/src/cmd/compile/internal/types2/api.go -@@ -208,11 +208,19 @@ type Info struct { - // - // The Types map does not record the type of every identifier, - // only those that appear where an arbitrary expression is -- // permitted. For instance, the identifier f in a selector -- // expression x.f is found only in the Selections map, the -- // identifier z in a variable declaration 'var z int' is found -- // only in the Defs map, and identifiers denoting packages in -- // qualified identifiers are collected in the Uses map. -+ // permitted. For instance: -+ // - an identifier f in a selector expression x.f is found -+ // only in the Selections map; -+ // - an identifier z in a variable declaration 'var z int' -+ // is found only in the Defs map; -+ // - an identifier p denoting a package in a qualified -+ // identifier p.X is found only in the Uses map. -+ // -+ // Similarly, no type is recorded for the (synthetic) FuncType -+ // node in a FuncDecl.Type field, since there is no corresponding -+ // syntactic function type expression in the source in this case -+ // Instead, the function type is found in the Defs.map entry for -+ // the corresponding function declaration. - Types map[syntax.Expr]TypeAndValue - - // If StoreTypesInSyntax is set, type information identical to -diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go -index d3169630ea..de4f1eaa20 100644 ---- a/src/cmd/compile/internal/types2/signature.go -+++ b/src/cmd/compile/internal/types2/signature.go -@@ -174,7 +174,7 @@ func (check *Checker) collectRecv(rparam *syntax.Field, scopePos syntax.Pos) (*V - } else { - // If there are type parameters, rbase must denote a generic base type. - // Important: rbase must be resolved before declaring any receiver type -- // parameters (wich may have the same name, see below). -+ // parameters (which may have the same name, see below). - var baseType *Named // nil if not valid - var cause string - if t := check.genericType(rbase, &cause); isValid(t) { -diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go -index 5a981f8bc1..0c992118f4 100644 ---- a/src/cmd/dist/test.go -+++ b/src/cmd/dist/test.go -@@ -876,16 +876,18 @@ func (t *tester) registerTests() { - } - - if t.extLink() && !t.compileOnly { -- t.registerTest("external linking, -buildmode=exe", -- &goTest{ -- variant: "exe_external", -- timeout: 60 * time.Second, -- buildmode: "exe", -- ldflags: "-linkmode=external", -- env: []string{"CGO_ENABLED=1"}, -- pkg: "crypto/internal/fips140test", -- runTests: "TestFIPSCheck", -- }) -+ if goos != "android" { // Android does not support non-PIE linking -+ t.registerTest("external linking, -buildmode=exe", -+ &goTest{ -+ variant: "exe_external", -+ timeout: 60 * time.Second, -+ buildmode: "exe", -+ ldflags: "-linkmode=external", -+ env: []string{"CGO_ENABLED=1"}, -+ pkg: "crypto/internal/fips140test", -+ runTests: "TestFIPSCheck", -+ }) -+ } - if t.externalLinkPIE() && !disablePIE { - t.registerTest("external linking, -buildmode=pie", - &goTest{ -@@ -1795,6 +1797,8 @@ func isEnvSet(evar string) bool { - } - - func (t *tester) fipsSupported() bool { -+ // Keep this in sync with [crypto/internal/fips140.Supported]. -+ - // Use GOFIPS140 or GOEXPERIMENT=boringcrypto, but not both. - if strings.Contains(goexperiment, "boringcrypto") { - return false -@@ -1808,6 +1812,7 @@ func (t *tester) fipsSupported() bool { - case goarch == "wasm", - goos == "windows" && goarch == "386", - goos == "windows" && goarch == "arm", -+ goos == "openbsd", - goos == "aix": - return false - } -diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go -index 3a4473902c..20d76de0c7 100644 ---- a/src/cmd/go/alldocs.go -+++ b/src/cmd/go/alldocs.go -@@ -739,11 +739,6 @@ - // - // For more about specifying packages, see 'go help packages'. - // --// This text describes the behavior of get using modules to manage source --// code and dependencies. If instead the go command is running in GOPATH --// mode, the details of get's flags and effects change, as does 'go help get'. --// See 'go help gopath-get'. --// - // See also: go build, go install, go clean, go mod. - // - // # Compile and install packages and dependencies -@@ -2186,7 +2181,7 @@ - // fields of all events to reconstruct the text format output, as it would - // have appeared from go build without the -json flag. - // --// Note that there may also be non-JSON error text on stdnard error, even -+// Note that there may also be non-JSON error text on standard error, even - // with the -json flag. Typically, this indicates an early, serious error. - // Consumers should be robust to this. - // -@@ -2250,7 +2245,7 @@ - // - // The second is the SWIG program, which is a general tool for - // interfacing between languages. For information on SWIG see --// http://swig.org/. When running go build, any file with a .swig -+// https://swig.org/. When running go build, any file with a .swig - // extension will be passed to SWIG. Any file with a .swigcxx extension - // will be passed to SWIG with the -c++ option. - // -@@ -2338,6 +2333,10 @@ - // GOCACHE - // The directory where the go command will store cached - // information for reuse in future builds. -+// GOCACHEPROG -+// A command (with optional space-separated flags) that implements an -+// external go command build cache. -+// See 'go doc cmd/go/internal/cacheprog'. - // GODEBUG - // Enable various debugging facilities. See https://go.dev/doc/godebug - // for details. -@@ -2448,6 +2447,11 @@ - // GOARM - // For GOARCH=arm, the ARM architecture for which to compile. - // Valid values are 5, 6, 7. -+// When the Go tools are built on an arm system, -+// the default value is set based on what the build system supports. -+// When the Go tools are not built on an arm system -+// (that is, when building a cross-compiler), -+// the default value is 7. - // The value can be followed by an option specifying how to implement floating point instructions. - // Valid options are ,softfloat (default for 5) and ,hardfloat (default for 6 and 7). - // GOARM64 -@@ -2612,7 +2616,7 @@ - // Example: Data - // - // If the server responds with any 4xx code, the go command will write the --// following to the programs' stdin: -+// following to the program's stdin: - // Response = StatusLine { HeaderLine } BlankLine . - // StatusLine = Protocol Space Status '\n' . - // Protocol = /* HTTP protocol */ . -@@ -2969,11 +2973,7 @@ - // same meta tag and then git clone https://code.org/r/p/exproj into - // GOPATH/src/example.org. - // --// When using GOPATH, downloaded packages are written to the first directory --// listed in the GOPATH environment variable. --// (See 'go help gopath-get' and 'go help gopath'.) --// --// When using modules, downloaded packages are stored in the module cache. -+// Downloaded packages are stored in the module cache. - // See https://golang.org/ref/mod#module-cache. - // - // When using modules, an additional variant of the go-import meta tag is -diff --git a/src/cmd/go/internal/cache/cache.go b/src/cmd/go/internal/cache/cache.go -index 98bed2a595..1bef1db08c 100644 ---- a/src/cmd/go/internal/cache/cache.go -+++ b/src/cmd/go/internal/cache/cache.go -@@ -38,8 +38,8 @@ type Cache interface { - // Get returns the cache entry for the provided ActionID. - // On miss, the error type should be of type *entryNotFoundError. - // -- // After a success call to Get, OutputFile(Entry.OutputID) must -- // exist on disk for until Close is called (at the end of the process). -+ // After a successful call to Get, OutputFile(Entry.OutputID) must -+ // exist on disk until Close is called (at the end of the process). - Get(ActionID) (Entry, error) - - // Put adds an item to the cache. -@@ -50,14 +50,14 @@ type Cache interface { - // As a special case, if the ReadSeeker is of type noVerifyReadSeeker, - // the verification from GODEBUG=goverifycache=1 is skipped. - // -- // After a success call to Get, OutputFile(Entry.OutputID) must -- // exist on disk for until Close is called (at the end of the process). -+ // After a successful call to Put, OutputFile(OutputID) must -+ // exist on disk until Close is called (at the end of the process). - Put(ActionID, io.ReadSeeker) (_ OutputID, size int64, _ error) - - // Close is called at the end of the go process. Implementations can do - // cache cleanup work at this phase, or wait for and report any errors from -- // background cleanup work started earlier. Any cache trimming should in one -- // process should not violate cause the invariants of this interface to be -+ // background cleanup work started earlier. Any cache trimming in one -+ // process should not cause the invariants of this interface to be - // violated in another process. Namely, a cache trim from one process should - // not delete an ObjectID from disk that was recently Get or Put from - // another process. As a rule of thumb, don't trim things used in the last -@@ -296,19 +296,19 @@ func GetBytes(c Cache, id ActionID) ([]byte, Entry, error) { - // GetMmap looks up the action ID in the cache and returns - // the corresponding output bytes. - // GetMmap should only be used for data that can be expected to fit in memory. --func GetMmap(c Cache, id ActionID) ([]byte, Entry, error) { -+func GetMmap(c Cache, id ActionID) ([]byte, Entry, bool, error) { - entry, err := c.Get(id) - if err != nil { -- return nil, entry, err -+ return nil, entry, false, err - } -- md, err := mmap.Mmap(c.OutputFile(entry.OutputID)) -+ md, opened, err := mmap.Mmap(c.OutputFile(entry.OutputID)) - if err != nil { -- return nil, Entry{}, err -+ return nil, Entry{}, opened, err - } - if int64(len(md.Data)) != entry.Size { -- return nil, Entry{}, &entryNotFoundError{Err: errors.New("file incomplete")} -+ return nil, Entry{}, true, &entryNotFoundError{Err: errors.New("file incomplete")} - } -- return md.Data, entry, nil -+ return md.Data, entry, true, nil - } - - // OutputFile returns the name of the cache file storing output with the given OutputID. -diff --git a/src/cmd/go/internal/cache/default.go b/src/cmd/go/internal/cache/default.go -index 074f911593..f8e5696cbd 100644 ---- a/src/cmd/go/internal/cache/default.go -+++ b/src/cmd/go/internal/cache/default.go -@@ -54,8 +54,8 @@ func initDefaultCache() Cache { - base.Fatalf("failed to initialize build cache at %s: %s\n", dir, err) - } - -- if v := cfg.Getenv("GOCACHEPROG"); v != "" { -- return startCacheProg(v, diskCache) -+ if cfg.GOCACHEPROG != "" { -+ return startCacheProg(cfg.GOCACHEPROG, diskCache) - } - - return diskCache -diff --git a/src/cmd/go/internal/cache/prog.go b/src/cmd/go/internal/cache/prog.go -index e09620bac8..bfddf5e4de 100644 ---- a/src/cmd/go/internal/cache/prog.go -+++ b/src/cmd/go/internal/cache/prog.go -@@ -7,6 +7,7 @@ package cache - import ( - "bufio" - "cmd/go/internal/base" -+ "cmd/go/internal/cacheprog" - "cmd/internal/quoted" - "context" - "crypto/sha256" -@@ -38,7 +39,7 @@ type ProgCache struct { - - // can are the commands that the child process declared that it supports. - // This is effectively the versioning mechanism. -- can map[ProgCmd]bool -+ can map[cacheprog.Cmd]bool - - // fuzzDirCache is another Cache implementation to use for the FuzzDir - // method. In practice this is the default GOCACHE disk-based -@@ -55,7 +56,7 @@ type ProgCache struct { - - mu sync.Mutex // guards following fields - nextID int64 -- inFlight map[int64]chan<- *ProgResponse -+ inFlight map[int64]chan<- *cacheprog.Response - outputFile map[OutputID]string // object => abs path on disk - - // writeMu serializes writing to the child process. -@@ -63,95 +64,6 @@ type ProgCache struct { - writeMu sync.Mutex - } - --// ProgCmd is a command that can be issued to a child process. --// --// If the interface needs to grow, we can add new commands or new versioned --// commands like "get2". --type ProgCmd string -- --const ( -- cmdGet = ProgCmd("get") -- cmdPut = ProgCmd("put") -- cmdClose = ProgCmd("close") --) -- --// ProgRequest is the JSON-encoded message that's sent from cmd/go to --// the GOCACHEPROG child process over stdin. Each JSON object is on its --// own line. A ProgRequest of Type "put" with BodySize > 0 will be followed --// by a line containing a base64-encoded JSON string literal of the body. --type ProgRequest struct { -- // ID is a unique number per process across all requests. -- // It must be echoed in the ProgResponse from the child. -- ID int64 -- -- // Command is the type of request. -- // The cmd/go tool will only send commands that were declared -- // as supported by the child. -- Command ProgCmd -- -- // ActionID is non-nil for get and puts. -- ActionID []byte `json:",omitempty"` // or nil if not used -- -- // OutputID is set for Type "put". -- // -- // Prior to Go 1.24, when GOCACHEPROG was still an experiment, this was -- // accidentally named ObjectID. It was renamed to OutputID in Go 1.24. -- OutputID []byte `json:",omitempty"` // or nil if not used -- -- // Body is the body for "put" requests. It's sent after the JSON object -- // as a base64-encoded JSON string when BodySize is non-zero. -- // It's sent as a separate JSON value instead of being a struct field -- // send in this JSON object so large values can be streamed in both directions. -- // The base64 string body of a ProgRequest will always be written -- // immediately after the JSON object and a newline. -- Body io.Reader `json:"-"` -- -- // BodySize is the number of bytes of Body. If zero, the body isn't written. -- BodySize int64 `json:",omitempty"` -- -- // ObjectID is the accidental spelling of OutputID that was used prior to Go -- // 1.24. -- // -- // Deprecated: use OutputID. This field is only populated temporarily for -- // backwards compatibility with Go 1.23 and earlier when -- // GOEXPERIMENT=gocacheprog is set. It will be removed in Go 1.25. -- ObjectID []byte `json:",omitempty"` --} -- --// ProgResponse is the JSON response from the child process to cmd/go. --// --// With the exception of the first protocol message that the child writes to its --// stdout with ID==0 and KnownCommands populated, these are only sent in --// response to a ProgRequest from cmd/go. --// --// ProgResponses can be sent in any order. The ID must match the request they're --// replying to. --type ProgResponse struct { -- ID int64 // that corresponds to ProgRequest; they can be answered out of order -- Err string `json:",omitempty"` // if non-empty, the error -- -- // KnownCommands is included in the first message that cache helper program -- // writes to stdout on startup (with ID==0). It includes the -- // ProgRequest.Command types that are supported by the program. -- // -- // This lets us extend the protocol gracefully over time (adding "get2", -- // etc), or fail gracefully when needed. It also lets us verify the program -- // wants to be a cache helper. -- KnownCommands []ProgCmd `json:",omitempty"` -- -- // For Get requests. -- -- Miss bool `json:",omitempty"` // cache miss -- OutputID []byte `json:",omitempty"` -- Size int64 `json:",omitempty"` // in bytes -- Time *time.Time `json:",omitempty"` // an Entry.Time; when the object was added to the docs -- -- // DiskPath is the absolute path on disk of the ObjectID corresponding -- // a "get" request's ActionID (on cache hit) or a "put" request's -- // provided ObjectID. -- DiskPath string `json:",omitempty"` --} -- - // startCacheProg starts the prog binary (with optional space-separated flags) - // and returns a Cache implementation that talks to it. - // -@@ -183,6 +95,8 @@ func startCacheProg(progAndArgs string, fuzzDirCache Cache) Cache { - base.Fatalf("StdinPipe to GOCACHEPROG: %v", err) - } - cmd.Stderr = os.Stderr -+ // On close, we cancel the context. Rather than killing the helper, -+ // close its stdin. - cmd.Cancel = in.Close - - if err := cmd.Start(); err != nil { -@@ -197,14 +111,14 @@ func startCacheProg(progAndArgs string, fuzzDirCache Cache) Cache { - stdout: out, - stdin: in, - bw: bufio.NewWriter(in), -- inFlight: make(map[int64]chan<- *ProgResponse), -+ inFlight: make(map[int64]chan<- *cacheprog.Response), - outputFile: make(map[OutputID]string), - readLoopDone: make(chan struct{}), - } - - // Register our interest in the initial protocol message from the child to - // us, saying what it can do. -- capResc := make(chan *ProgResponse, 1) -+ capResc := make(chan *cacheprog.Response, 1) - pc.inFlight[0] = capResc - - pc.jenc = json.NewEncoder(pc.bw) -@@ -219,7 +133,7 @@ func startCacheProg(progAndArgs string, fuzzDirCache Cache) Cache { - case <-timer.C: - log.Printf("# still waiting for GOCACHEPROG %v ...", prog) - case capRes := <-capResc: -- can := map[ProgCmd]bool{} -+ can := map[cacheprog.Cmd]bool{} - for _, cmd := range capRes.KnownCommands { - can[cmd] = true - } -@@ -236,9 +150,15 @@ func (c *ProgCache) readLoop(readLoopDone chan<- struct{}) { - defer close(readLoopDone) - jd := json.NewDecoder(c.stdout) - for { -- res := new(ProgResponse) -+ res := new(cacheprog.Response) - if err := jd.Decode(res); err != nil { - if c.closing.Load() { -+ c.mu.Lock() -+ for _, ch := range c.inFlight { -+ close(ch) -+ } -+ c.inFlight = nil -+ c.mu.Unlock() - return // quietly - } - if err == io.EOF { -@@ -261,13 +181,18 @@ func (c *ProgCache) readLoop(readLoopDone chan<- struct{}) { - } - } - --func (c *ProgCache) send(ctx context.Context, req *ProgRequest) (*ProgResponse, error) { -- resc := make(chan *ProgResponse, 1) -+var errCacheprogClosed = errors.New("GOCACHEPROG program closed unexpectedly") -+ -+func (c *ProgCache) send(ctx context.Context, req *cacheprog.Request) (*cacheprog.Response, error) { -+ resc := make(chan *cacheprog.Response, 1) - if err := c.writeToChild(req, resc); err != nil { - return nil, err - } - select { - case res := <-resc: -+ if res == nil { -+ return nil, errCacheprogClosed -+ } - if res.Err != "" { - return nil, errors.New(res.Err) - } -@@ -277,8 +202,11 @@ func (c *ProgCache) send(ctx context.Context, req *ProgRequest) (*ProgResponse, - } - } - --func (c *ProgCache) writeToChild(req *ProgRequest, resc chan<- *ProgResponse) (err error) { -+func (c *ProgCache) writeToChild(req *cacheprog.Request, resc chan<- *cacheprog.Response) (err error) { - c.mu.Lock() -+ if c.inFlight == nil { -+ return errCacheprogClosed -+ } - c.nextID++ - req.ID = c.nextID - c.inFlight[req.ID] = resc -@@ -287,7 +215,9 @@ func (c *ProgCache) writeToChild(req *ProgRequest, resc chan<- *ProgResponse) (e - defer func() { - if err != nil { - c.mu.Lock() -- delete(c.inFlight, req.ID) -+ if c.inFlight != nil { -+ delete(c.inFlight, req.ID) -+ } - c.mu.Unlock() - } - }() -@@ -328,7 +258,7 @@ func (c *ProgCache) writeToChild(req *ProgRequest, resc chan<- *ProgResponse) (e - } - - func (c *ProgCache) Get(a ActionID) (Entry, error) { -- if !c.can[cmdGet] { -+ if !c.can[cacheprog.CmdGet] { - // They can't do a "get". Maybe they're a write-only cache. - // - // TODO(bradfitz,bcmills): figure out the proper error type here. Maybe -@@ -338,8 +268,8 @@ func (c *ProgCache) Get(a ActionID) (Entry, error) { - // error types on the Cache interface. - return Entry{}, &entryNotFoundError{} - } -- res, err := c.send(c.ctx, &ProgRequest{ -- Command: cmdGet, -+ res, err := c.send(c.ctx, &cacheprog.Request{ -+ Command: cacheprog.CmdGet, - ActionID: a[:], - }) - if err != nil { -@@ -395,7 +325,7 @@ func (c *ProgCache) Put(a ActionID, file io.ReadSeeker) (_ OutputID, size int64, - return OutputID{}, 0, err - } - -- if !c.can[cmdPut] { -+ if !c.can[cacheprog.CmdPut] { - // Child is a read-only cache. Do nothing. - return out, size, nil - } -@@ -407,8 +337,8 @@ func (c *ProgCache) Put(a ActionID, file io.ReadSeeker) (_ OutputID, size int64, - deprecatedValue = out[:] - } - -- res, err := c.send(c.ctx, &ProgRequest{ -- Command: cmdPut, -+ res, err := c.send(c.ctx, &cacheprog.Request{ -+ Command: cacheprog.CmdPut, - ActionID: a[:], - OutputID: out[:], - ObjectID: deprecatedValue, // TODO(bradfitz): remove in Go 1.25 -@@ -432,10 +362,16 @@ func (c *ProgCache) Close() error { - // First write a "close" message to the child so it can exit nicely - // and clean up if it wants. Only after that exchange do we cancel - // the context that kills the process. -- if c.can[cmdClose] { -- _, err = c.send(c.ctx, &ProgRequest{Command: cmdClose}) -+ if c.can[cacheprog.CmdClose] { -+ _, err = c.send(c.ctx, &cacheprog.Request{Command: cacheprog.CmdClose}) -+ if errors.Is(err, errCacheprogClosed) { -+ // Allow the child to quit without responding to close. -+ err = nil -+ } - } -+ // Cancel the context, which will close the helper's stdin. - c.ctxCancel() -+ // Wait until the helper closes its stdout. - <-c.readLoopDone - return err - } -diff --git a/src/cmd/go/internal/cacheprog/cacheprog.go b/src/cmd/go/internal/cacheprog/cacheprog.go -new file mode 100644 -index 0000000000..a2796592df ---- /dev/null -+++ b/src/cmd/go/internal/cacheprog/cacheprog.go -@@ -0,0 +1,137 @@ -+// Copyright 2024 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package cacheprog defines the protocol for a GOCACHEPROG program. -+// -+// By default, the go command manages a build cache stored in the file system -+// itself. GOCACHEPROG can be set to the name of a command (with optional -+// space-separated flags) that implements the go command build cache externally. -+// This permits defining a different cache policy. -+// -+// The go command will start the GOCACHEPROG as a subprocess and communicate -+// with it via JSON messages over stdin/stdout. The subprocess's stderr will be -+// connected to the go command's stderr. -+// -+// The subprocess should immediately send a [Response] with its capabilities. -+// After that, the go command will send a stream of [Request] messages and the -+// subprocess should reply to each [Request] with a [Response] message. -+package cacheprog -+ -+import ( -+ "io" -+ "time" -+) -+ -+// Cmd is a command that can be issued to a child process. -+// -+// If the interface needs to grow, the go command can add new commands or new -+// versioned commands like "get2" in the future. The initial [Response] from -+// the child process indicates which commands it supports. -+type Cmd string -+ -+const ( -+ // CmdPut tells the cache program to store an object in the cache. -+ // -+ // [Request.ActionID] is the cache key of this object. The cache should -+ // store [Request.OutputID] and [Request.Body] under this key for a -+ // later "get" request. It must also store the Body in a file in the local -+ // file system and return the path to that file in [Response.DiskPath], -+ // which must exist at least until a "close" request. -+ CmdPut = Cmd("put") -+ -+ // CmdGet tells the cache program to retrieve an object from the cache. -+ // -+ // [Request.ActionID] specifies the key of the object to get. If the -+ // cache does not contain this object, it should set [Response.Miss] to -+ // true. Otherwise, it should populate the fields of [Response], -+ // including setting [Response.OutputID] to the OutputID of the original -+ // "put" request and [Response.DiskPath] to the path of a local file -+ // containing the Body of the original "put" request. That file must -+ // continue to exist at least until a "close" request. -+ CmdGet = Cmd("get") -+ -+ // CmdClose requests that the cache program exit gracefully. -+ // -+ // The cache program should reply to this request and then exit -+ // (thus closing its stdout). -+ CmdClose = Cmd("close") -+) -+ -+// Request is the JSON-encoded message that's sent from the go command to -+// the GOCACHEPROG child process over stdin. Each JSON object is on its own -+// line. A ProgRequest of Type "put" with BodySize > 0 will be followed by a -+// line containing a base64-encoded JSON string literal of the body. -+type Request struct { -+ // ID is a unique number per process across all requests. -+ // It must be echoed in the Response from the child. -+ ID int64 -+ -+ // Command is the type of request. -+ // The go command will only send commands that were declared -+ // as supported by the child. -+ Command Cmd -+ -+ // ActionID is the cache key for "put" and "get" requests. -+ ActionID []byte `json:",omitempty"` // or nil if not used -+ -+ // OutputID is stored with the body for "put" requests. -+ // -+ // Prior to Go 1.24, when GOCACHEPROG was still an experiment, this was -+ // accidentally named ObjectID. It was renamed to OutputID in Go 1.24. -+ OutputID []byte `json:",omitempty"` // or nil if not used -+ -+ // Body is the body for "put" requests. It's sent after the JSON object -+ // as a base64-encoded JSON string when BodySize is non-zero. -+ // It's sent as a separate JSON value instead of being a struct field -+ // send in this JSON object so large values can be streamed in both directions. -+ // The base64 string body of a Request will always be written -+ // immediately after the JSON object and a newline. -+ Body io.Reader `json:"-"` -+ -+ // BodySize is the number of bytes of Body. If zero, the body isn't written. -+ BodySize int64 `json:",omitempty"` -+ -+ // ObjectID is the accidental spelling of OutputID that was used prior to Go -+ // 1.24. -+ // -+ // Deprecated: use OutputID. This field is only populated temporarily for -+ // backwards compatibility with Go 1.23 and earlier when -+ // GOEXPERIMENT=gocacheprog is set. It will be removed in Go 1.25. -+ ObjectID []byte `json:",omitempty"` -+} -+ -+// Response is the JSON response from the child process to the go command. -+// -+// With the exception of the first protocol message that the child writes to its -+// stdout with ID==0 and KnownCommands populated, these are only sent in -+// response to a Request from the go command. -+// -+// Responses can be sent in any order. The ID must match the request they're -+// replying to. -+type Response struct { -+ ID int64 // that corresponds to Request; they can be answered out of order -+ Err string `json:",omitempty"` // if non-empty, the error -+ -+ // KnownCommands is included in the first message that cache helper program -+ // writes to stdout on startup (with ID==0). It includes the -+ // Request.Command types that are supported by the program. -+ // -+ // This lets the go command extend the protocol gracefully over time (adding -+ // "get2", etc), or fail gracefully when needed. It also lets the go command -+ // verify the program wants to be a cache helper. -+ KnownCommands []Cmd `json:",omitempty"` -+ -+ // For "get" requests. -+ -+ Miss bool `json:",omitempty"` // cache miss -+ OutputID []byte `json:",omitempty"` // the ObjectID stored with the body -+ Size int64 `json:",omitempty"` // body size in bytes -+ Time *time.Time `json:",omitempty"` // when the object was put in the cache (optional; used for cache expiration) -+ -+ // For "get" and "put" requests. -+ -+ // DiskPath is the absolute path on disk of the body corresponding to a -+ // "get" (on cache hit) or "put" request's ActionID. -+ DiskPath string `json:",omitempty"` -+} -diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go -index 6c2af99c2d..3b9f27e91d 100644 ---- a/src/cmd/go/internal/cfg/cfg.go -+++ b/src/cmd/go/internal/cfg/cfg.go -@@ -425,8 +425,9 @@ var ( - GOROOTpkg string - GOROOTsrc string - -- GOBIN = Getenv("GOBIN") -- GOMODCACHE, GOMODCACHEChanged = EnvOrAndChanged("GOMODCACHE", gopathDir("pkg/mod")) -+ GOBIN = Getenv("GOBIN") -+ GOCACHEPROG, GOCACHEPROGChanged = EnvOrAndChanged("GOCACHEPROG", "") -+ GOMODCACHE, GOMODCACHEChanged = EnvOrAndChanged("GOMODCACHE", gopathDir("pkg/mod")) - - // Used in envcmd.MkEnv and build ID computations. - GOARM64, goARM64Changed = EnvOrAndChanged("GOARM64", buildcfg.DefaultGOARM64) -diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go -index 19db68e4f8..7c370d427f 100644 ---- a/src/cmd/go/internal/envcmd/env.go -+++ b/src/cmd/go/internal/envcmd/env.go -@@ -85,6 +85,7 @@ func MkEnv() []cfg.EnvVar { - {Name: "GOAUTH", Value: cfg.GOAUTH, Changed: cfg.GOAUTHChanged}, - {Name: "GOBIN", Value: cfg.GOBIN}, - {Name: "GOCACHE"}, -+ {Name: "GOCACHEPROG", Value: cfg.GOCACHEPROG, Changed: cfg.GOCACHEPROGChanged}, - {Name: "GODEBUG", Value: os.Getenv("GODEBUG")}, - {Name: "GOENV", Value: envFile, Changed: envFileChanged}, - {Name: "GOEXE", Value: cfg.ExeSuffix}, -diff --git a/src/cmd/go/internal/fips140/fips140.go b/src/cmd/go/internal/fips140/fips140.go -index 7c04a94dd1..328e06088e 100644 ---- a/src/cmd/go/internal/fips140/fips140.go -+++ b/src/cmd/go/internal/fips140/fips140.go -@@ -40,14 +40,8 @@ - // - // GOFIPS140=latest go build -work my/binary - // --// will leave fips.o behind in $WORK/b001. Auditors like to be able to --// see that file. Accordingly, when [Enabled] returns true, --// [cmd/go/internal/work.Builder.useCache] arranges never to cache linker --// output, so that the link step always runs, and fips.o is always left --// behind in the link step. If this proves too slow, we could always --// cache fips.o as an extra link output and then restore it when -work is --// set, but we went a very long time never caching link steps at all, so --// not caching them in FIPS mode seems perfectly fine. -+// will leave fips.o behind in $WORK/b001 -+// (unless the build result is cached, of course). - // - // When GOFIPS140 is set to something besides off and latest, [Snapshot] - // returns true, indicating that the build should replace the latest copy -@@ -119,6 +113,10 @@ func Init() { - if Snapshot() { - fsys.Bind(Dir(), filepath.Join(cfg.GOROOT, "src/crypto/internal/fips140")) - } -+ -+ if cfg.Experiment.BoringCrypto && Enabled() { -+ base.Fatalf("go: cannot use GOFIPS140 with GOEXPERIMENT=boringcrypto") -+ } - } - - var initDone bool -diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go -index e1240de710..65d0f1a45c 100644 ---- a/src/cmd/go/internal/help/helpdoc.go -+++ b/src/cmd/go/internal/help/helpdoc.go -@@ -17,7 +17,7 @@ information on how to use it see the cgo documentation (go doc cmd/cgo). - - The second is the SWIG program, which is a general tool for - interfacing between languages. For information on SWIG see --http://swig.org/. When running go build, any file with a .swig -+https://swig.org/. When running go build, any file with a .swig - extension will be passed to SWIG. Any file with a .swigcxx extension - will be passed to SWIG with the -c++ option. - -@@ -270,11 +270,7 @@ the go tool will verify that https://example.org/?go-get=1 contains the - same meta tag and then git clone https://code.org/r/p/exproj into - GOPATH/src/example.org. - --When using GOPATH, downloaded packages are written to the first directory --listed in the GOPATH environment variable. --(See 'go help gopath-get' and 'go help gopath'.) -- --When using modules, downloaded packages are stored in the module cache. -+Downloaded packages are stored in the module cache. - See https://golang.org/ref/mod#module-cache. - - When using modules, an additional variant of the go-import meta tag is -@@ -510,6 +506,10 @@ General-purpose environment variables: - GOCACHE - The directory where the go command will store cached - information for reuse in future builds. -+ GOCACHEPROG -+ A command (with optional space-separated flags) that implements an -+ external go command build cache. -+ See 'go doc cmd/go/internal/cacheprog'. - GODEBUG - Enable various debugging facilities. See https://go.dev/doc/godebug - for details. -@@ -620,6 +620,11 @@ Architecture-specific environment variables: - GOARM - For GOARCH=arm, the ARM architecture for which to compile. - Valid values are 5, 6, 7. -+ When the Go tools are built on an arm system, -+ the default value is set based on what the build system supports. -+ When the Go tools are not built on an arm system -+ (that is, when building a cross-compiler), -+ the default value is 7. - The value can be followed by an option specifying how to implement floating point instructions. - Valid options are ,softfloat (default for 5) and ,hardfloat (default for 6 and 7). - GOARM64 -@@ -1029,7 +1034,7 @@ command - Example: Data - - If the server responds with any 4xx code, the go command will write the -- following to the programs' stdin: -+ following to the program's stdin: - Response = StatusLine { HeaderLine } BlankLine . - StatusLine = Protocol Space Status '\n' . - Protocol = /* HTTP protocol */ . -@@ -1097,7 +1102,7 @@ Furthermore, as with TestEvent, parsers can simply concatenate the Output - fields of all events to reconstruct the text format output, as it would - have appeared from go build without the -json flag. - --Note that there may also be non-JSON error text on stdnard error, even -+Note that there may also be non-JSON error text on standard error, even - with the -json flag. Typically, this indicates an early, serious error. - Consumers should be robust to this. - `, -diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go -index df790e1eaa..15f6b2e87b 100644 ---- a/src/cmd/go/internal/load/pkg.go -+++ b/src/cmd/go/internal/load/pkg.go -@@ -3068,7 +3068,15 @@ func setPGOProfilePath(pkgs []*Package) { - // CheckPackageErrors prints errors encountered loading pkgs and their - // dependencies, then exits with a non-zero status if any errors were found. - func CheckPackageErrors(pkgs []*Package) { -- var anyIncomplete bool -+ PackageErrors(pkgs, func(p *Package) { -+ DefaultPrinter().Errorf(p, "%v", p.Error) -+ }) -+ base.ExitIfErrors() -+} -+ -+// PackageErrors calls report for errors encountered loading pkgs and their dependencies. -+func PackageErrors(pkgs []*Package, report func(*Package)) { -+ var anyIncomplete, anyErrors bool - for _, pkg := range pkgs { - if pkg.Incomplete { - anyIncomplete = true -@@ -3078,11 +3086,14 @@ func CheckPackageErrors(pkgs []*Package) { - all := PackageList(pkgs) - for _, p := range all { - if p.Error != nil { -- DefaultPrinter().Errorf(p, "%v", p.Error) -+ report(p) -+ anyErrors = true - } - } - } -- base.ExitIfErrors() -+ if anyErrors { -+ return -+ } - - // Check for duplicate loads of the same package. - // That should be impossible, but if it does happen then -@@ -3105,7 +3116,9 @@ func CheckPackageErrors(pkgs []*Package) { - } - seen[key] = true - } -- base.ExitIfErrors() -+ if len(reported) > 0 { -+ base.ExitIfErrors() -+ } - } - - // mainPackagesOnly filters out non-main packages matched only by arguments -diff --git a/src/cmd/go/internal/mmap/mmap.go b/src/cmd/go/internal/mmap/mmap.go -index fcbd3e08c1..fd374df82e 100644 ---- a/src/cmd/go/internal/mmap/mmap.go -+++ b/src/cmd/go/internal/mmap/mmap.go -@@ -22,10 +22,11 @@ type Data struct { - } - - // Mmap maps the given file into memory. --func Mmap(file string) (Data, error) { -+func Mmap(file string) (Data, bool, error) { - f, err := os.Open(file) - if err != nil { -- return Data{}, err -+ return Data{}, false, err - } -- return mmapFile(f) -+ data, err := mmapFile(f) -+ return data, true, err - } -diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go -index 159a856911..48ae12fe53 100644 ---- a/src/cmd/go/internal/modget/get.go -+++ b/src/cmd/go/internal/modget/get.go -@@ -125,11 +125,6 @@ suggested Go toolchain, see https://go.dev/doc/toolchain. - - For more about specifying packages, see 'go help packages'. - --This text describes the behavior of get using modules to manage source --code and dependencies. If instead the go command is running in GOPATH --mode, the details of get's flags and effects change, as does 'go help get'. --See 'go help gopath-get'. -- - See also: go build, go install, go clean, go mod. - `, - } -diff --git a/src/cmd/go/internal/modindex/read.go b/src/cmd/go/internal/modindex/read.go -index c4102409b4..4c1fbd8359 100644 ---- a/src/cmd/go/internal/modindex/read.go -+++ b/src/cmd/go/internal/modindex/read.go -@@ -183,16 +183,21 @@ func openIndexModule(modroot string, ismodcache bool) (*Module, error) { - if err != nil { - return nil, err - } -- data, _, err := cache.GetMmap(cache.Default(), id) -+ data, _, opened, err := cache.GetMmap(cache.Default(), id) - if err != nil { - // Couldn't read from modindex. Assume we couldn't read from - // the index because the module hasn't been indexed yet. -+ // But double check on Windows that we haven't opened the file yet, -+ // because once mmap opens the file, we can't close it, and -+ // Windows won't let us open an already opened file. - data, err = indexModule(modroot) - if err != nil { - return nil, err - } -- if err = cache.PutBytes(cache.Default(), id, data); err != nil { -- return nil, err -+ if runtime.GOOS != "windows" || !opened { -+ if err = cache.PutBytes(cache.Default(), id, data); err != nil { -+ return nil, err -+ } - } - } - mi, err := fromBytes(modroot, data) -@@ -212,13 +217,18 @@ func openIndexPackage(modroot, pkgdir string) (*IndexPackage, error) { - if err != nil { - return nil, err - } -- data, _, err := cache.GetMmap(cache.Default(), id) -+ data, _, opened, err := cache.GetMmap(cache.Default(), id) - if err != nil { - // Couldn't read from index. Assume we couldn't read from - // the index because the package hasn't been indexed yet. -+ // But double check on Windows that we haven't opened the file yet, -+ // because once mmap opens the file, we can't close it, and -+ // Windows won't let us open an already opened file. - data = indexPackage(modroot, pkgdir) -- if err = cache.PutBytes(cache.Default(), id, data); err != nil { -- return nil, err -+ if runtime.GOOS != "windows" || !opened { -+ if err = cache.PutBytes(cache.Default(), id, data); err != nil { -+ return nil, err -+ } - } - } - pkg, err := packageFromBytes(modroot, data) -diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go -index 41ddb2f5d0..90f2d88d6b 100644 ---- a/src/cmd/go/internal/test/test.go -+++ b/src/cmd/go/internal/test/test.go -@@ -994,14 +994,15 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { - - // Prepare build + run + print actions for all packages being tested. - for _, p := range pkgs { -- buildTest, runTest, printTest, perr, err := builderTest(b, ctx, pkgOpts, p, allImports[p], writeCoverMetaAct) -- if err != nil { -+ reportErr := func(perr *load.Package, err error) { - str := err.Error() - if p.ImportPath != "" { - load.DefaultPrinter().Errorf(perr, "# %s\n%s", p.ImportPath, str) - } else { - load.DefaultPrinter().Errorf(perr, "%s", str) - } -+ } -+ reportSetupFailed := func(perr *load.Package, err error) { - var stdout io.Writer = os.Stdout - if testJSON { - json := test2json.NewConverter(stdout, p.ImportPath, test2json.Timestamp) -@@ -1009,11 +1010,34 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { - json.Exited(err) - json.Close() - }() -- json.SetFailedBuild(perr.Desc()) -+ if gotestjsonbuildtext.Value() == "1" { -+ // While this flag is about go build -json, the other effect -+ // of that change was to include "FailedBuild" in the test JSON. -+ gotestjsonbuildtext.IncNonDefault() -+ } else { -+ json.SetFailedBuild(perr.Desc()) -+ } - stdout = json - } - fmt.Fprintf(stdout, "FAIL\t%s [setup failed]\n", p.ImportPath) - base.SetExitStatus(1) -+ } -+ -+ var firstErrPkg *load.Package // arbitrarily report setup failed error for first error pkg reached in DFS -+ load.PackageErrors([]*load.Package{p}, func(p *load.Package) { -+ reportErr(p, p.Error) -+ if firstErrPkg == nil { -+ firstErrPkg = p -+ } -+ }) -+ if firstErrPkg != nil { -+ reportSetupFailed(firstErrPkg, firstErrPkg.Error) -+ continue -+ } -+ buildTest, runTest, printTest, perr, err := builderTest(b, ctx, pkgOpts, p, allImports[p], writeCoverMetaAct) -+ if err != nil { -+ reportErr(perr, err) -+ reportSetupFailed(perr, err) - continue - } - builds = append(builds, buildTest) -@@ -1437,7 +1461,11 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action) - if a.Failed != nil { - // We were unable to build the binary. - if json != nil && a.Failed.Package != nil { -- json.SetFailedBuild(a.Failed.Package.Desc()) -+ if gotestjsonbuildtext.Value() == "1" { -+ gotestjsonbuildtext.IncNonDefault() -+ } else { -+ json.SetFailedBuild(a.Failed.Package.Desc()) -+ } - } - a.Failed = nil - fmt.Fprintf(stdout, "FAIL\t%s [build failed]\n", a.Package.ImportPath) -diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go -index cbdd7a2418..aeab59519c 100644 ---- a/src/cmd/go/internal/toolchain/select.go -+++ b/src/cmd/go/internal/toolchain/select.go -@@ -169,7 +169,7 @@ func Select() { - } - - gotoolchain = minToolchain -- if (mode == "auto" || mode == "path") && !goInstallVersion() { -+ if (mode == "auto" || mode == "path") && !goInstallVersion(minVers) { - // Read go.mod to find new minimum and suggested toolchain. - file, goVers, toolchain := modGoToolchain() - gover.Startup.AutoFile = file -@@ -549,7 +549,7 @@ func modGoToolchain() (file, goVers, toolchain string) { - - // goInstallVersion reports whether the command line is go install m@v or go run m@v. - // If so, Select must not read the go.mod or go.work file in "auto" or "path" mode. --func goInstallVersion() bool { -+func goInstallVersion(minVers string) bool { - // Note: We assume there are no flags between 'go' and 'install' or 'run'. - // During testing there are some debugging flags that are accepted - // in that position, but in production go binaries there are not. -@@ -708,7 +708,11 @@ func goInstallVersion() bool { - if errors.Is(err, gover.ErrTooNew) { - // Run early switch, same one go install or go run would eventually do, - // if it understood all the command-line flags. -- SwitchOrFatal(ctx, err) -+ var s Switcher -+ s.Error(err) -+ if s.TooNew != nil && gover.Compare(s.TooNew.GoVersion, minVers) > 0 { -+ SwitchOrFatal(ctx, err) -+ } - } - - return true // pkg@version found -diff --git a/src/cmd/go/internal/vcweb/auth.go b/src/cmd/go/internal/vcweb/auth.go -index 383bf759ff..e7c7c6ca26 100644 ---- a/src/cmd/go/internal/vcweb/auth.go -+++ b/src/cmd/go/internal/vcweb/auth.go -@@ -63,6 +63,7 @@ func (h *authHandler) Handler(dir string, env []string, logger *log.Logger) (htt - var err error - accessFile, err = fs.Open(path.Join(accessDir, ".access")) - if err == nil { -+ defer accessFile.Close() - break - } - -diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go -index 55b3190300..cab722c28a 100644 ---- a/src/cmd/go/internal/work/buildid.go -+++ b/src/cmd/go/internal/work/buildid.go -@@ -15,7 +15,6 @@ import ( - "cmd/go/internal/base" - "cmd/go/internal/cache" - "cmd/go/internal/cfg" -- "cmd/go/internal/fips140" - "cmd/go/internal/fsys" - "cmd/go/internal/str" - "cmd/internal/buildid" -@@ -447,19 +446,6 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string, - a.buildID = actionID + buildIDSeparator + mainpkg.buildID + buildIDSeparator + contentID - } - -- // In FIPS mode, we disable any link caching, -- // so that we always leave fips.o in $WORK/b001. -- // This makes sure that labs validating the FIPS -- // implementation can always run 'go build -work' -- // and then find fips.o in $WORK/b001/fips.o. -- // We could instead also save the fips.o and restore it -- // to $WORK/b001 from the cache, -- // but we went years without caching binaries anyway, -- // so not caching them for FIPS will be fine, at least to start. -- if a.Mode == "link" && fips140.Enabled() && a.Package != nil && !strings.HasSuffix(a.Package.ImportPath, ".test") { -- return false -- } -- - // If user requested -a, we force a rebuild, so don't use the cache. - if cfg.BuildA { - if p := a.Package; p != nil && !p.Stale { -@@ -519,7 +505,7 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string, - oldBuildID := a.buildID - a.buildID = id[1] + buildIDSeparator + id[2] - linkID := buildid.HashToString(b.linkActionID(a.triggers[0])) -- if id[0] == linkID && !fips140.Enabled() { -+ if id[0] == linkID { - // Best effort attempt to display output from the compile and link steps. - // If it doesn't work, it doesn't work: reusing the cached binary is more - // important than reprinting diagnostic information. -diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go -index 2538fae52f..7b073165d5 100644 ---- a/src/cmd/go/internal/work/exec.go -+++ b/src/cmd/go/internal/work/exec.go -@@ -1374,6 +1374,7 @@ func (b *Builder) linkActionID(a *Action) cache.ActionID { - fmt.Fprintf(h, "buildmode %s goos %s goarch %s\n", cfg.BuildBuildmode, cfg.Goos, cfg.Goarch) - fmt.Fprintf(h, "import %q\n", p.ImportPath) - fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix) -+ fmt.Fprintf(h, "defaultgodebug %q\n", p.DefaultGODEBUG) - if cfg.BuildTrimpath { - fmt.Fprintln(h, "trimpath") - } -diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go -index 1e2f81b2d4..33341a4f4d 100644 ---- a/src/cmd/go/internal/work/security.go -+++ b/src/cmd/go/internal/work/security.go -@@ -201,23 +201,23 @@ var validLinkerFlags = []*lazyregexp.Regexp{ - re(`-Wl,--end-group`), - re(`-Wl,--(no-)?export-dynamic`), - re(`-Wl,-E`), -- re(`-Wl,-framework,[^,@\-][^,]+`), -+ re(`-Wl,-framework,[^,@\-][^,]*`), - re(`-Wl,--hash-style=(sysv|gnu|both)`), - re(`-Wl,-headerpad_max_install_names`), - re(`-Wl,--no-undefined`), - re(`-Wl,--pop-state`), - re(`-Wl,--push-state`), - re(`-Wl,-R,?([^@\-,][^,@]*$)`), -- re(`-Wl,--just-symbols[=,]([^,@\-][^,@]+)`), -- re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]+)`), -+ re(`-Wl,--just-symbols[=,]([^,@\-][^,@]*)`), -+ re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]*)`), - re(`-Wl,-s`), - re(`-Wl,-search_paths_first`), -- re(`-Wl,-sectcreate,([^,@\-][^,]+),([^,@\-][^,]+),([^,@\-][^,]+)`), -+ re(`-Wl,-sectcreate,([^,@\-][^,]*),([^,@\-][^,]*),([^,@\-][^,]*)`), - re(`-Wl,--start-group`), - re(`-Wl,-?-static`), - re(`-Wl,-?-subsystem,(native|windows|console|posix|xbox)`), -- re(`-Wl,-syslibroot[=,]([^,@\-][^,]+)`), -- re(`-Wl,-undefined[=,]([^,@\-][^,]+)`), -+ re(`-Wl,-syslibroot[=,]([^,@\-][^,]*)`), -+ re(`-Wl,-undefined[=,]([^,@\-][^,]*)`), - re(`-Wl,-?-unresolved-symbols=[^,]+`), - re(`-Wl,--(no-)?warn-([^,]+)`), - re(`-Wl,-?-wrap[=,][^,@\-][^,]*`), -@@ -227,6 +227,21 @@ var validLinkerFlags = []*lazyregexp.Regexp{ - re(`\./.*\.(a|o|obj|dll|dylib|so|tbd)`), - } - -+var validLinkerFlagsOnDarwin = []*lazyregexp.Regexp{ -+ // The GNU linker interprets `@file` as "read command-line options from -+ // file". Thus, we forbid values starting with `@` on linker flags. -+ // However, this causes a problem when targeting Darwin. -+ // `@executable_path`, `@loader_path`, and `@rpath` are special values -+ // used in Mach-O to change the library search path and can be used in -+ // conjunction with the `-install_name` and `-rpath` linker flags. -+ // Since the GNU linker does not support Mach-O, targeting Darwin -+ // implies not using the GNU linker. Therefore, we allow @ in the linker -+ // flags if and only if cfg.Goos == "darwin" || cfg.Goos == "ios". -+ re(`-Wl,-dylib_install_name,@rpath(/[^,]*)?`), -+ re(`-Wl,-install_name,@rpath(/[^,]*)?`), -+ re(`-Wl,-rpath,@(executable_path|loader_path)(/[^,]*)?`), -+} -+ - var validLinkerFlagsWithNextArg = []string{ - "-arch", - "-F", -@@ -249,8 +264,13 @@ func checkCompilerFlags(name, source string, list []string) error { - } - - func checkLinkerFlags(name, source string, list []string) error { -+ validLinkerFlagsForPlatform := validLinkerFlags -+ if cfg.Goos == "darwin" || cfg.Goos == "ios" { -+ validLinkerFlagsForPlatform = append(validLinkerFlags, validLinkerFlagsOnDarwin...) -+ } -+ - checkOverrides := true -- return checkFlags(name, source, list, invalidLinkerFlags, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides) -+ return checkFlags(name, source, list, invalidLinkerFlags, validLinkerFlagsForPlatform, validLinkerFlagsWithNextArg, checkOverrides) - } - - // checkCompilerFlagsForInternalLink returns an error if 'list' -diff --git a/src/cmd/go/internal/work/security_test.go b/src/cmd/go/internal/work/security_test.go -index 63dd569f7d..52e54e25e4 100644 ---- a/src/cmd/go/internal/work/security_test.go -+++ b/src/cmd/go/internal/work/security_test.go -@@ -8,6 +8,8 @@ import ( - "os" - "strings" - "testing" -+ -+ "cmd/go/internal/cfg" - ) - - var goodCompilerFlags = [][]string{ -@@ -182,6 +184,13 @@ var goodLinkerFlags = [][]string{ - {"-Wl,--pop-state"}, - {"-Wl,--push-state,--as-needed"}, - {"-Wl,--push-state,--no-as-needed,-Bstatic"}, -+ {"-Wl,--just-symbols,."}, -+ {"-Wl,-framework,."}, -+ {"-Wl,-rpath,."}, -+ {"-Wl,-rpath-link,."}, -+ {"-Wl,-sectcreate,.,.,."}, -+ {"-Wl,-syslibroot,."}, -+ {"-Wl,-undefined,."}, - } - - var badLinkerFlags = [][]string{ -@@ -238,6 +247,8 @@ var badLinkerFlags = [][]string{ - {"-Wl,--hash-style=foo"}, - {"-x", "--c"}, - {"-x", "@obj"}, -+ {"-Wl,-dylib_install_name,@foo"}, -+ {"-Wl,-install_name,@foo"}, - {"-Wl,-rpath,@foo"}, - {"-Wl,-R,foo,bar"}, - {"-Wl,-R,@foo"}, -@@ -254,6 +265,21 @@ var badLinkerFlags = [][]string{ - {"./-Wl,--push-state,-R.c"}, - } - -+var goodLinkerFlagsOnDarwin = [][]string{ -+ {"-Wl,-dylib_install_name,@rpath"}, -+ {"-Wl,-dylib_install_name,@rpath/"}, -+ {"-Wl,-dylib_install_name,@rpath/foo"}, -+ {"-Wl,-install_name,@rpath"}, -+ {"-Wl,-install_name,@rpath/"}, -+ {"-Wl,-install_name,@rpath/foo"}, -+ {"-Wl,-rpath,@executable_path"}, -+ {"-Wl,-rpath,@executable_path/"}, -+ {"-Wl,-rpath,@executable_path/foo"}, -+ {"-Wl,-rpath,@loader_path"}, -+ {"-Wl,-rpath,@loader_path/"}, -+ {"-Wl,-rpath,@loader_path/foo"}, -+} -+ - func TestCheckLinkerFlags(t *testing.T) { - for _, f := range goodLinkerFlags { - if err := checkLinkerFlags("test", "test", f); err != nil { -@@ -265,6 +291,31 @@ func TestCheckLinkerFlags(t *testing.T) { - t.Errorf("missing error for %q", f) - } - } -+ -+ goos := cfg.Goos -+ -+ cfg.Goos = "darwin" -+ for _, f := range goodLinkerFlagsOnDarwin { -+ if err := checkLinkerFlags("test", "test", f); err != nil { -+ t.Errorf("unexpected error for %q: %v", f, err) -+ } -+ } -+ -+ cfg.Goos = "ios" -+ for _, f := range goodLinkerFlagsOnDarwin { -+ if err := checkLinkerFlags("test", "test", f); err != nil { -+ t.Errorf("unexpected error for %q: %v", f, err) -+ } -+ } -+ -+ cfg.Goos = "linux" -+ for _, f := range goodLinkerFlagsOnDarwin { -+ if err := checkLinkerFlags("test", "test", f); err == nil { -+ t.Errorf("missing error for %q", f) -+ } -+ } -+ -+ cfg.Goos = goos - } - - func TestCheckFlagAllowDisallow(t *testing.T) { -diff --git a/src/cmd/go/testdata/script/build_cacheprog_issue70848.txt b/src/cmd/go/testdata/script/build_cacheprog_issue70848.txt -new file mode 100644 -index 0000000000..194fd47d93 ---- /dev/null -+++ b/src/cmd/go/testdata/script/build_cacheprog_issue70848.txt -@@ -0,0 +1,27 @@ -+[short] skip 'builds go programs' -+ -+go build -o cacheprog$GOEXE cacheprog.go -+env GOCACHEPROG=$GOPATH/src/cacheprog$GOEXE -+ -+# This should not deadlock -+go build simple.go -+! stderr 'cacheprog closed' -+ -+-- simple.go -- -+package main -+ -+func main() {} -+-- cacheprog.go -- -+// This is a minimal GOCACHEPROG program that doesn't respond to close. -+package main -+ -+import ( -+ "encoding/json" -+ "os" -+) -+ -+func main() { -+ json.NewEncoder(os.Stdout).Encode(map[string][]string{"KnownCommands": {"close"}}) -+ var res struct{} -+ json.NewDecoder(os.Stdin).Decode(&res) -+} -\ No newline at end of file -diff --git a/src/cmd/go/testdata/script/build_version_stamping_git.txt b/src/cmd/go/testdata/script/build_version_stamping_git.txt -index ed07e00c7b..db804b3847 100644 ---- a/src/cmd/go/testdata/script/build_version_stamping_git.txt -+++ b/src/cmd/go/testdata/script/build_version_stamping_git.txt -@@ -51,7 +51,7 @@ go version -m example$GOEXE - stdout '\s+mod\s+example\s+v1.0.1\s+' - rm example$GOEXE - --# Use tag+dirty when there are uncomitted changes present. -+# Use tag+dirty when there are uncommitted changes present. - cp $WORK/copy/README $WORK/repo/README - go build - go version -m example$GOEXE -@@ -82,7 +82,7 @@ go version -m example$GOEXE - stdout '\s+mod\s+example\s+v1.0.3-0.20220719150702-deaeab06f7fe\s+' - rm example$GOEXE - --# Use pseudo+dirty when uncomitted changes are present. -+# Use pseudo+dirty when uncommitted changes are present. - mv README2 README3 - go build - go version -m example$GOEXE -diff --git a/src/cmd/go/testdata/script/env_changed.txt b/src/cmd/go/testdata/script/env_changed.txt -index f57f69bfd7..10db765407 100644 ---- a/src/cmd/go/testdata/script/env_changed.txt -+++ b/src/cmd/go/testdata/script/env_changed.txt -@@ -1,5 +1,8 @@ - # Test query for non-defaults in the env - -+# Go+BoringCrypto conflicts with GOFIPS140. -+[GOEXPERIMENT:boringcrypto] skip -+ - env GOROOT=./a - env GOTOOLCHAIN=local - env GOSUMDB=nodefault -diff --git a/src/cmd/go/testdata/script/env_gocacheprog.txt b/src/cmd/go/testdata/script/env_gocacheprog.txt -new file mode 100644 -index 0000000000..1547bf058c ---- /dev/null -+++ b/src/cmd/go/testdata/script/env_gocacheprog.txt -@@ -0,0 +1,42 @@ -+# GOCACHEPROG unset -+env GOCACHEPROG= -+ -+go env -+stdout 'GOCACHEPROG=''?''?' -+ -+go env -changed -+! stdout 'GOCACHEPROG' -+ -+go env -changed -json -+! stdout 'GOCACHEPROG' -+ -+# GOCACHEPROG set -+[short] skip 'compiles and runs a go program' -+ -+go build -o cacheprog$GOEXE cacheprog.go -+ -+env GOCACHEPROG=$GOPATH/src/cacheprog$GOEXE -+ -+go env -+stdout 'GOCACHEPROG=''?'$GOCACHEPROG'''?' -+ -+go env -changed -+stdout 'GOCACHEPROG=''?'$GOCACHEPROG'''?' -+ -+go env -changed -json -+stdout '"GOCACHEPROG": ".*cacheprog'$GOEXE'"' -+ -+-- cacheprog.go -- -+// This is a minimal GOCACHEPROG program that can't actually do anything but exit. -+package main -+ -+import ( -+ "encoding/json" -+ "os" -+) -+ -+func main() { -+ json.NewEncoder(os.Stdout).Encode(map[string][]string{"KnownCommands": {"close"}}) -+ var res struct{} -+ json.NewDecoder(os.Stdin).Decode(&res) -+} -\ No newline at end of file -diff --git a/src/cmd/go/testdata/script/fips.txt b/src/cmd/go/testdata/script/fips.txt -index fd791d3990..374902eb70 100644 ---- a/src/cmd/go/testdata/script/fips.txt -+++ b/src/cmd/go/testdata/script/fips.txt -@@ -1,3 +1,6 @@ -+# Go+BoringCrypto conflicts with GOFIPS140. -+[GOEXPERIMENT:boringcrypto] skip -+ - # list with GOFIPS140=off - env GOFIPS140=off - go list -f '{{.DefaultGODEBUG}}' -@@ -17,12 +20,12 @@ go build -x -o x.exe - go build -x -o x.exe - ! stderr link - --# build with GOFIPS140=latest is NOT cached (need fipso) -+# build with GOFIPS140=latest is cached too - env GOFIPS140=latest - go build -x -o x.exe - stderr link.*-fipso - go build -x -o x.exe --stderr link.*-fipso -+! stderr link.*-fipso - - # build test with GOFIPS140=off is cached - env GOFIPS140=off -@@ -38,8 +41,6 @@ stderr link.*-fipso - go test -x -c - ! stderr link - -- -- - -- go.mod -- - module m - -- x.go -- -diff --git a/src/cmd/go/testdata/script/fipssnap.txt b/src/cmd/go/testdata/script/fipssnap.txt -index 17a9d647a1..465f304c46 100644 ---- a/src/cmd/go/testdata/script/fipssnap.txt -+++ b/src/cmd/go/testdata/script/fipssnap.txt -@@ -7,6 +7,9 @@ env alias=inprocess - skip 'no snapshots yet' - env GOFIPS140=$snap - -+# Go+BoringCrypto conflicts with GOFIPS140. -+[GOEXPERIMENT:boringcrypto] skip -+ - # default GODEBUG includes fips140=on - go list -f '{{.DefaultGODEBUG}}' - stdout fips140=on -@@ -44,11 +47,11 @@ stdout crypto/internal/fips140/$snap/sha256 - - [short] skip - --# build with GOFIPS140=snap is NOT cached (need fipso) -+# build with GOFIPS140=snap is cached - go build -x -o x.exe - stderr link.*-fipso - go build -x -o x.exe --stderr link.*-fipso -+! stderr link.*-fipso - - # build test with GOFIPS140=snap is cached - go test -x -c -diff --git a/src/cmd/go/testdata/script/gotoolchain_local.txt b/src/cmd/go/testdata/script/gotoolchain_local.txt -index db7e082db9..8bece6ebd8 100644 ---- a/src/cmd/go/testdata/script/gotoolchain_local.txt -+++ b/src/cmd/go/testdata/script/gotoolchain_local.txt -@@ -197,6 +197,17 @@ go mod edit -go=1.501 -toolchain=none - go version - stdout go1.501 - -+# avoid two-step switch, first from install target requirement, then from GOTOOLCHAIN min -+# instead, just jump directly to GOTOOLCHAIN min -+env TESTGO_VERSION=go1.2.3 -+env GODEBUG=toolchaintrace=1 -+env GOTOOLCHAIN=go1.23.0+auto -+! go install rsc.io/fortune/nonexist@v0.0.1 -+! stderr 'switching to go1.22.9' -+stderr 'using go1.23.0' -+env GODEBUG= -+env GOTOOLCHAIN=auto -+ - # go install m@v and go run m@v should ignore go.mod and use m@v - env TESTGO_VERSION=go1.2.3 - go mod edit -go=1.999 -toolchain=go1.998 -diff --git a/src/cmd/go/testdata/script/mod_help.txt b/src/cmd/go/testdata/script/mod_help.txt -index b5cd30c521..7cb808ff23 100644 ---- a/src/cmd/go/testdata/script/mod_help.txt -+++ b/src/cmd/go/testdata/script/mod_help.txt -@@ -3,4 +3,4 @@ env GO111MODULE=on - # go help get shows usage for get - go help get - stdout 'usage: go get' --stdout 'get using modules to manage source' -\ No newline at end of file -+stdout 'updates go.mod to require those versions' -diff --git a/src/cmd/go/testdata/script/test_flags.txt b/src/cmd/go/testdata/script/test_flags.txt -index 7adf4e273c..afef08840d 100644 ---- a/src/cmd/go/testdata/script/test_flags.txt -+++ b/src/cmd/go/testdata/script/test_flags.txt -@@ -15,8 +15,8 @@ stdout '\Aok\s+example.com/x\s+[0-9.s]+\n\z' - # Even though ./x looks like a package path, the real package should be - # the implicit '.'. - ! go test --answer=42 ./x --stdout '^FAIL\t. \[build failed\]' --stderr '^\.: no Go files in '$PWD'$' -+stdout '^FAIL\t. \[setup failed\]' -+stderr '^# \.\nno Go files in '$PWD'$' - - # However, *flags* that appear after unrecognized flags should still be - # interpreted as flags, under the (possibly-erroneous) assumption that -diff --git a/src/cmd/go/testdata/script/test_fuzz_context.txt b/src/cmd/go/testdata/script/test_fuzz_context.txt -new file mode 100644 -index 0000000000..a830684708 ---- /dev/null -+++ b/src/cmd/go/testdata/script/test_fuzz_context.txt -@@ -0,0 +1,47 @@ -+[!fuzz] skip -+[short] skip -+env GOCACHE=$WORK/cache -+ -+# Test fuzz.Context. -+go test -vet=off context_fuzz_test.go -+stdout ^ok -+! stdout FAIL -+ -+go test -vet=off -fuzz=Fuzz -fuzztime=1x context_fuzz_test.go -+stdout ok -+! stdout FAIL -+ -+-- context_fuzz_test.go -- -+package context_fuzz -+ -+import ( -+ "context" -+ "errors" -+ "testing" -+) -+ -+func Fuzz(f *testing.F) { -+ ctx := f.Context() -+ if err := ctx.Err(); err != nil { -+ f.Fatalf("expected non-canceled context, got %v", err) -+ } -+ -+ f.Fuzz(func(t *testing.T, data []byte) { -+ innerCtx := t.Context() -+ if err := innerCtx.Err(); err != nil { -+ t.Fatalf("expected inner test to not inherit canceled context, got %v", err) -+ } -+ -+ t.Cleanup(func() { -+ if !errors.Is(innerCtx.Err(), context.Canceled) { -+ t.Fatal("expected context of inner test to be canceled after its fuzz function finished") -+ } -+ }) -+ }) -+ -+ f.Cleanup(func() { -+ if !errors.Is(ctx.Err(), context.Canceled) { -+ f.Fatal("expected context canceled before cleanup") -+ } -+ }) -+} -diff --git a/src/cmd/go/testdata/script/test_json_build.txt b/src/cmd/go/testdata/script/test_json_build.txt -index a3f0c37923..df8863ae03 100644 ---- a/src/cmd/go/testdata/script/test_json_build.txt -+++ b/src/cmd/go/testdata/script/test_json_build.txt -@@ -40,6 +40,18 @@ stdout '"Action":"output","Package":"m/loaderror","Output":"FAIL\\tm/loaderror \ - stdout '"Action":"fail","Package":"m/loaderror","Elapsed":.*,"FailedBuild":"x"' - ! stderr '.' - -+# Test an import cycle loading error in a non test file. (#70820) -+! go test -json -o=$devnull ./cycle/p -+stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"# m/cycle/p\\n"' -+stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"package m/cycle/p\\n"' -+stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"\\timports m/cycle/q from p.go\\n"' -+stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"\\timports m/cycle/q from q.go: import cycle not allowed\\n"' -+stdout '"ImportPath":"m/cycle/q","Action":"build-fail"' -+stdout '"Action":"start","Package":"m/cycle/p"' -+stdout '"Action":"output","Package":"m/cycle/p","Output":"FAIL\\tm/cycle/p \[setup failed\]\\n"' -+stdout '"Action":"fail","Package":"m/cycle/p","Elapsed":.*,"FailedBuild":"m/cycle/q"' -+! stderr '.' -+ - # Test a vet error - ! go test -json -o=$devnull ./veterror - stdout '"ImportPath":"m/veterror \[m/veterror.test\]","Action":"build-output","Output":"# m/veterror\\n"' -@@ -58,8 +70,9 @@ stderr '# m/builderror \[m/builderror.test\]\n' - stderr 'builderror'${/}'main_test.go:3:11: undefined: y\n' - stdout '"Action":"start","Package":"m/builderror"' - stdout '"Action":"output","Package":"m/builderror","Output":"FAIL\\tm/builderror \[build failed\]\\n"' --stdout '"Action":"fail","Package":"m/builderror","Elapsed":.*,"FailedBuild":"m/builderror \[m/builderror\.test\]"' -- -+stdout '"Action":"fail","Package":"m/builderror","Elapsed":[0-9.]+\}' -+# FailedBuild should NOT appear in the output in this mode. -+! stdout '"FailedBuild"' - - -- go.mod -- - module m -@@ -98,3 +111,13 @@ import ( - func TestVetError(t *testing.T) { - fmt.Printf("%s") - } -+-- cycle/p/p.go -- -+package p -+ -+import "m/cycle/q" -+-- cycle/q/q.go -- -+package q -+ -+import ( -+ "m/cycle/q" -+) -diff --git a/src/cmd/go/testdata/script/test_setup_error.txt b/src/cmd/go/testdata/script/test_setup_error.txt -index 2999067f2c..bf566d4621 100644 ---- a/src/cmd/go/testdata/script/test_setup_error.txt -+++ b/src/cmd/go/testdata/script/test_setup_error.txt -@@ -33,10 +33,23 @@ stderr '# m/t2/p\n.*package x is not in std' - stdout 'FAIL m/t2/p \[setup failed\]' - stdout 'ok m/t' - --# Finally, this one is a build error, but produced by cmd/go directly -+# Test that an import cycle error is reported. Test for #70820 -+! go test -o=$devnull ./cycle/p ./t -+stderr '# m/cycle/p\n.*package m/cycle/p\n\timports m/cycle/p from p\.go: import cycle not allowed' -+stdout 'FAIL m/cycle/p \[setup failed\]' -+stdout 'ok m/t' -+ -+# Test that multiple errors for the same package under test are reported. -+! go test -o=$devnull ./cycle/q ./t -+stderr '# m/cycle/q\n.*package m/cycle/q\n\timports m/cycle/p from q\.go\n\timports m/cycle/p from p\.go: import cycle not allowed' -+stdout 'FAIL m/cycle/q \[setup failed\]' -+stdout 'ok m/t' -+ -+# Finally, this one is a non-import-cycle load error that -+# is produced for the package under test. - ! go test -o=$devnull . ./t --stderr '^\.: no Go files in '$PWD'$' --stdout 'FAIL . \[build failed\]' -+stderr '# \.\n.*no Go files in '$PWD'$' -+stdout 'FAIL . \[setup failed\]' - stdout 'ok m/t' - - -- go.mod -- -@@ -68,6 +81,17 @@ package p - package p - - import "m/bad" -+-- cycle/p/p.go -- -+package p -+ -+import "m/cycle/p" -+-- cycle/q/q.go -- -+package q -+ -+import ( -+ "m/bad" -+ "m/cycle/p" -+) - -- bad/bad.go -- - package bad - -diff --git a/src/cmd/internal/disasm/disasm.go b/src/cmd/internal/disasm/disasm.go -index c317effa90..3ae8989b38 100644 ---- a/src/cmd/internal/disasm/disasm.go -+++ b/src/cmd/internal/disasm/disasm.go -@@ -410,14 +410,16 @@ func disasm_ppc64(code []byte, pc uint64, lookup lookupFunc, byteOrder binary.By - func disasm_riscv64(code []byte, pc uint64, lookup lookupFunc, byteOrder binary.ByteOrder, gnuAsm bool) (string, int) { - inst, err := riscv64asm.Decode(code) - var text string -+ size := inst.Len - if err != nil || inst.Op == 0 { -+ size = 2 - text = "?" - } else if gnuAsm { - text = fmt.Sprintf("%-36s // %s", riscv64asm.GoSyntax(inst, pc, lookup, textReader{code, pc}), riscv64asm.GNUSyntax(inst)) - } else { - text = riscv64asm.GoSyntax(inst, pc, lookup, textReader{code, pc}) - } -- return text, 4 -+ return text, size - } - - func disasm_s390x(code []byte, pc uint64, lookup lookupFunc, _ binary.ByteOrder, gnuAsm bool) (string, int) { -diff --git a/src/cmd/internal/hash/hash.go b/src/cmd/internal/hash/hash.go -index 20edc72c20..a37368f50e 100644 ---- a/src/cmd/internal/hash/hash.go -+++ b/src/cmd/internal/hash/hash.go -@@ -5,22 +5,33 @@ - // Package hash implements hash functions used in the compiler toolchain. - package hash - -+// TODO(rsc): Delete the 16 and 20 forms and use 32 at all call sites. -+ - import ( -- "crypto/md5" -- "crypto/sha1" - "crypto/sha256" - "hash" - ) - - const ( -- // Size32 is the size of 32 bytes hash checksum. -- Size32 = sha256.Size -- // Size20 is the size of 20 bytes hash checksum. -- Size20 = sha1.Size -- // Size16 is the size of 16 bytes hash checksum. -- Size16 = md5.Size -+ // Size32 is the size of the 32-byte hash checksum. -+ Size32 = 32 -+ // Size20 is the size of the 20-byte hash checksum. -+ Size20 = 20 -+ // Size16 is the size of the 16-byte hash checksum. -+ Size16 = 16 - ) - -+type shortHash struct { -+ hash.Hash -+ n int -+} -+ -+func (h *shortHash) Sum(b []byte) []byte { -+ old := b -+ sum := h.Hash.Sum(b) -+ return sum[:len(old)+h.n] -+} -+ - // New32 returns a new [hash.Hash] computing the 32 bytes hash checksum. - func New32() hash.Hash { - h := sha256.New() -@@ -30,12 +41,12 @@ func New32() hash.Hash { - - // New20 returns a new [hash.Hash] computing the 20 bytes hash checksum. - func New20() hash.Hash { -- return sha1.New() -+ return &shortHash{New32(), 20} - } - - // New16 returns a new [hash.Hash] computing the 16 bytes hash checksum. - func New16() hash.Hash { -- return md5.New() -+ return &shortHash{New32(), 16} - } - - // Sum32 returns the 32 bytes checksum of the data. -@@ -47,10 +58,16 @@ func Sum32(data []byte) [Size32]byte { - - // Sum20 returns the 20 bytes checksum of the data. - func Sum20(data []byte) [Size20]byte { -- return sha1.Sum(data) -+ sum := Sum32(data) -+ var short [Size20]byte -+ copy(short[:], sum[4:]) -+ return short - } - - // Sum16 returns the 16 bytes checksum of the data. - func Sum16(data []byte) [Size16]byte { -- return md5.Sum(data) -+ sum := Sum32(data) -+ var short [Size16]byte -+ copy(short[:], sum[8:]) -+ return short - } -diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go -index 4feccf54f6..8872579050 100644 ---- a/src/cmd/internal/obj/sym.go -+++ b/src/cmd/internal/obj/sym.go -@@ -320,7 +320,7 @@ func (ctxt *Link) NumberSyms() { - // Assign special index for builtin symbols. - // Don't do it when linking against shared libraries, as the runtime - // may be in a different library. -- if i := goobj.BuiltinIdx(rs.Name, int(rs.ABI())); i != -1 { -+ if i := goobj.BuiltinIdx(rs.Name, int(rs.ABI())); i != -1 && !rs.IsLinkname() { - rs.PkgIdx = goobj.PkgIdxBuiltin - rs.SymIdx = int32(i) - rs.Set(AttrIndexed, true) -diff --git a/src/cmd/link/doc.go b/src/cmd/link/doc.go -index 9ec2c002f4..7b548f960f 100644 ---- a/src/cmd/link/doc.go -+++ b/src/cmd/link/doc.go -@@ -118,6 +118,7 @@ Flags: - Link with race detection libraries. - -s - Omit the symbol table and debug information. -+ Implies the -w flag, which can be negated with -w=0. - -tmpdir dir - Write temporary files to dir. - Temporary files are only used in external linking mode. -diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go -index b6eaf69ca4..a6b94a829f 100644 ---- a/src/cmd/link/internal/ld/data.go -+++ b/src/cmd/link/internal/ld/data.go -@@ -55,17 +55,31 @@ import ( - ) - - // isRuntimeDepPkg reports whether pkg is the runtime package or its dependency. -+// TODO: just compute from the runtime package, and remove this hardcoded list. - func isRuntimeDepPkg(pkg string) bool { - switch pkg { - case "runtime", -- "sync/atomic", // runtime may call to sync/atomic, due to go:linkname -- "internal/abi", // used by reflectcall (and maybe more) -- "internal/bytealg", // for IndexByte -+ "sync/atomic", // runtime may call to sync/atomic, due to go:linkname // TODO: this is not true? -+ "internal/abi", // used by reflectcall (and maybe more) -+ "internal/asan", -+ "internal/bytealg", // for IndexByte -+ "internal/byteorder", - "internal/chacha8rand", // for rand -- "internal/cpu": // for cpu features -+ "internal/coverage/rtcov", -+ "internal/cpu", // for cpu features -+ "internal/goarch", -+ "internal/godebugs", -+ "internal/goexperiment", -+ "internal/goos", -+ "internal/msan", -+ "internal/profilerecord", -+ "internal/race", -+ "internal/stringslite", -+ "unsafe": - return true - } -- return strings.HasPrefix(pkg, "runtime/internal/") && !strings.HasSuffix(pkg, "_test") -+ return (strings.HasPrefix(pkg, "runtime/internal/") || strings.HasPrefix(pkg, "internal/runtime/")) && -+ !strings.HasSuffix(pkg, "_test") - } - - // Estimate the max size needed to hold any new trampolines created for this function. This -@@ -410,6 +424,9 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { - // FIXME: It should be forbidden to have R_ADDR from a - // symbol which isn't in .data. However, as .text has the - // same address once loaded, this is possible. -+ // TODO: .text (including rodata) to .data relocation -+ // doesn't work correctly, so we should really disallow it. -+ // See also aixStaticDataBase in symtab.go and in runtime. - if ldr.SymSect(s).Seg == &Segdata { - Xcoffadddynrel(target, ldr, syms, s, r, ri) - } -diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go -index 14c0b687d8..b653e09a3c 100644 ---- a/src/cmd/link/internal/ld/dwarf.go -+++ b/src/cmd/link/internal/ld/dwarf.go -@@ -520,7 +520,7 @@ func (d *dwctxt) defgotype(gotype loader.Sym) loader.Sym { - d.linkctxt.Errorf(gotype, "dwarf: type name doesn't start with \"type:\"") - return d.mustFind("
") - } -- name := sn[5:] // could also decode from Type.string -+ name := sn[len("type:"):] // could also decode from Type.string - - sdie := d.find(name) - if sdie != 0 { -@@ -534,7 +534,7 @@ func (d *dwctxt) defgotype(gotype loader.Sym) loader.Sym { - - func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { - sn := d.ldr.SymName(gotype) -- name := sn[5:] // could also decode from Type.string -+ name := sn[len("type:"):] // could also decode from Type.string - tdata := d.ldr.Data(gotype) - if len(tdata) == 0 { - d.linkctxt.Errorf(gotype, "missing type") -diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go -index 8156f83a7a..b89a7802a2 100644 ---- a/src/cmd/link/internal/ld/symtab.go -+++ b/src/cmd/link/internal/ld/symtab.go -@@ -707,6 +707,17 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { - // except go:buildid which is generated late and not used by the program. - addRef("go:buildid") - } -+ if ctxt.IsAIX() { -+ // On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol -+ // does not work. See data.go:relocsym, case R_ADDR. -+ // Here we record the unrelocated address in aixStaticDataBase (it is -+ // unrelocated as it is in RODATA) so we can compute the delta at -+ // run time. -+ sb := ldr.CreateSymForUpdate("runtime.aixStaticDataBase", 0) -+ sb.SetSize(0) -+ sb.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0)) -+ sb.SetType(sym.SRODATA) -+ } - - // text section information - slice(textsectionmapSym, uint64(nsections)) -diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go -index 6fe895a840..e7cc30ab07 100644 ---- a/src/cmd/link/internal/loader/loader.go -+++ b/src/cmd/link/internal/loader/loader.go -@@ -2338,6 +2338,45 @@ var blockedLinknames = map[string][]string{ - "runtime.newcoro": {"iter"}, - // fips info - "go:fipsinfo": {"crypto/internal/fips140/check"}, -+ // New internal linknames in Go 1.24 -+ // Pushed from runtime -+ "crypto/internal/fips140.fatal": {"crypto/internal/fips140"}, -+ "crypto/internal/fips140.getIndicator": {"crypto/internal/fips140"}, -+ "crypto/internal/fips140.setIndicator": {"crypto/internal/fips140"}, -+ "crypto/internal/sysrand.fatal": {"crypto/internal/sysrand"}, -+ "crypto/rand.fatal": {"crypto/rand"}, -+ "internal/runtime/maps.errNilAssign": {"internal/runtime/maps"}, -+ "internal/runtime/maps.fatal": {"internal/runtime/maps"}, -+ "internal/runtime/maps.mapKeyError": {"internal/runtime/maps"}, -+ "internal/runtime/maps.newarray": {"internal/runtime/maps"}, -+ "internal/runtime/maps.newobject": {"internal/runtime/maps"}, -+ "internal/runtime/maps.typedmemclr": {"internal/runtime/maps"}, -+ "internal/runtime/maps.typedmemmove": {"internal/runtime/maps"}, -+ "internal/sync.fatal": {"internal/sync"}, -+ "internal/sync.runtime_canSpin": {"internal/sync"}, -+ "internal/sync.runtime_doSpin": {"internal/sync"}, -+ "internal/sync.runtime_nanotime": {"internal/sync"}, -+ "internal/sync.runtime_Semrelease": {"internal/sync"}, -+ "internal/sync.runtime_SemacquireMutex": {"internal/sync"}, -+ "internal/sync.throw": {"internal/sync"}, -+ "internal/synctest.Run": {"internal/synctest"}, -+ "internal/synctest.Wait": {"internal/synctest"}, -+ "internal/synctest.acquire": {"internal/synctest"}, -+ "internal/synctest.release": {"internal/synctest"}, -+ "internal/synctest.inBubble": {"internal/synctest"}, -+ "runtime.getStaticuint64s": {"reflect"}, -+ "sync.runtime_SemacquireWaitGroup": {"sync"}, -+ "time.runtimeNow": {"time"}, -+ "time.runtimeNano": {"time"}, -+ // Pushed to runtime from internal/runtime/maps -+ // (other map functions are already linknamed in Go 1.23) -+ "runtime.mapaccess1": {"runtime"}, -+ "runtime.mapaccess1_fast32": {"runtime"}, -+ "runtime.mapaccess1_fast64": {"runtime"}, -+ "runtime.mapaccess1_faststr": {"runtime"}, -+ "runtime.mapdelete_fast32": {"runtime"}, -+ "runtime.mapdelete_fast64": {"runtime"}, -+ "runtime.mapdelete_faststr": {"runtime"}, - } - - // check if a linkname reference to symbol s from pkg is allowed -diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go -index f23951416b..ab56b49e15 100644 ---- a/src/cmd/link/link_test.go -+++ b/src/cmd/link/link_test.go -@@ -1518,6 +1518,8 @@ func TestCheckLinkname(t *testing.T) { - {"coro_asm", false}, - // pull-only linkname is not ok - {"coro2.go", false}, -+ // pull linkname of a builtin symbol is not ok -+ {"builtin.go", false}, - // legacy bad linkname is ok, for now - {"fastrand.go", true}, - {"badlinkname.go", true}, -diff --git a/src/cmd/link/testdata/linkname/builtin.go b/src/cmd/link/testdata/linkname/builtin.go -new file mode 100644 -index 0000000000..a238c9b967 ---- /dev/null -+++ b/src/cmd/link/testdata/linkname/builtin.go -@@ -0,0 +1,17 @@ -+// Copyright 2024 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Linkname builtin symbols (that is not already linknamed, -+// e.g. mapaccess1) is not allowed. -+ -+package main -+ -+import "unsafe" -+ -+func main() { -+ mapaccess1(nil, nil, nil) -+} -+ -+//go:linkname mapaccess1 runtime.mapaccess1 -+func mapaccess1(t, m, k unsafe.Pointer) unsafe.Pointer -diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go -index f1450dcbd2..3860895a0a 100644 ---- a/src/cmd/vet/vet_test.go -+++ b/src/cmd/vet/vet_test.go -@@ -108,7 +108,7 @@ func TestVet(t *testing.T) { - // is a no-op for files whose version >= go1.22, so we use a - // go.mod file in the rangeloop directory to "downgrade". - // -- // TOOD(adonovan): delete when go1.21 goes away. -+ // TODO(adonovan): delete when go1.21 goes away. - t.Run("loopclosure", func(t *testing.T) { - cmd := testenv.Command(t, testenv.GoToolPath(t), "vet", "-vettool="+vetPath(t), ".") - cmd.Env = append(os.Environ(), "GOWORK=off") -diff --git a/src/context/context.go b/src/context/context.go -index db8bc69553..bef9e8aab0 100644 ---- a/src/context/context.go -+++ b/src/context/context.go -@@ -10,23 +10,25 @@ - // calls to servers should accept a Context. The chain of function - // calls between them must propagate the Context, optionally replacing - // it with a derived Context created using [WithCancel], [WithDeadline], --// [WithTimeout], or [WithValue]. When a Context is canceled, all --// Contexts derived from it are also canceled. -+// [WithTimeout], or [WithValue]. -+// -+// A Context may be canceled to indicate that work done on its behalf should stop. -+// A Context with a deadline is canceled after the deadline passes. -+// When a Context is canceled, all Contexts derived from it are also canceled. - // - // The [WithCancel], [WithDeadline], and [WithTimeout] functions take a - // Context (the parent) and return a derived Context (the child) and a --// [CancelFunc]. Calling the CancelFunc cancels the child and its -+// [CancelFunc]. Calling the CancelFunc directly cancels the child and its - // children, removes the parent's reference to the child, and stops - // any associated timers. Failing to call the CancelFunc leaks the --// child and its children until the parent is canceled or the timer --// fires. The go vet tool checks that CancelFuncs are used on all --// control-flow paths. -+// child and its children until the parent is canceled. The go vet tool -+// checks that CancelFuncs are used on all control-flow paths. - // --// The [WithCancelCause] function returns a [CancelCauseFunc], which --// takes an error and records it as the cancellation cause. Calling --// [Cause] on the canceled context or any of its children retrieves --// the cause. If no cause is specified, Cause(ctx) returns the same --// value as ctx.Err(). -+// The [WithCancelCause], [WithDeadlineCause], and [WithTimeoutCause] functions -+// return a [CancelCauseFunc], which takes an error and records it as -+// the cancellation cause. Calling [Cause] on the canceled context -+// or any of its children retrieves the cause. If no cause is specified, -+// Cause(ctx) returns the same value as ctx.Err(). - // - // Programs that use Contexts should follow these rules to keep interfaces - // consistent across packages and enable static analysis tools to check context -@@ -107,8 +109,8 @@ type Context interface { - - // If Done is not yet closed, Err returns nil. - // If Done is closed, Err returns a non-nil error explaining why: -- // Canceled if the context was canceled -- // or DeadlineExceeded if the context's deadline passed. -+ // DeadlineExceeded if the context's deadline passed, -+ // or Canceled if the context was canceled for some other reason. - // After Err returns a non-nil error, successive calls to Err return the same error. - Err() error - -@@ -160,11 +162,12 @@ type Context interface { - Value(key any) any - } - --// Canceled is the error returned by [Context.Err] when the context is canceled. -+// Canceled is the error returned by [Context.Err] when the context is canceled -+// for some reason other than its deadline passing. - var Canceled = errors.New("context canceled") - --// DeadlineExceeded is the error returned by [Context.Err] when the context's --// deadline passes. -+// DeadlineExceeded is the error returned by [Context.Err] when the context is canceled -+// due to its deadline passing. - var DeadlineExceeded error = deadlineExceededError{} - - type deadlineExceededError struct{} -@@ -296,9 +299,8 @@ func Cause(c Context) error { - return c.Err() - } - --// AfterFunc arranges to call f in its own goroutine after ctx is done --// (canceled or timed out). --// If ctx is already done, AfterFunc calls f immediately in its own goroutine. -+// AfterFunc arranges to call f in its own goroutine after ctx is canceled. -+// If ctx is already canceled, AfterFunc calls f immediately in its own goroutine. - // - // Multiple calls to AfterFunc on a context operate independently; - // one does not replace another. -@@ -306,7 +308,7 @@ func Cause(c Context) error { - // Calling the returned stop function stops the association of ctx with f. - // It returns true if the call stopped f from being run. - // If stop returns false, --// either the context is done and f has been started in its own goroutine; -+// either the context is canceled and f has been started in its own goroutine; - // or f was already stopped. - // The stop function does not wait for f to complete before returning. - // If the caller needs to know whether f is completed, -diff --git a/src/context/example_test.go b/src/context/example_test.go -index b597b09f16..be8cd8376e 100644 ---- a/src/context/example_test.go -+++ b/src/context/example_test.go -@@ -146,8 +146,8 @@ func ExampleAfterFunc_cond() { - defer stopf() - - // Since the wakeups are using Broadcast instead of Signal, this call to -- // Wait may unblock due to some other goroutine's context becoming done, -- // so to be sure that ctx is actually done we need to check it in a loop. -+ // Wait may unblock due to some other goroutine's context being canceled, -+ // so to be sure that ctx is actually canceled we need to check it in a loop. - for !conditionMet() { - cond.Wait() - if ctx.Err() != nil { -diff --git a/src/crypto/cipher/cbc.go b/src/crypto/cipher/cbc.go -index b4536aceb9..8e61406296 100644 ---- a/src/crypto/cipher/cbc.go -+++ b/src/crypto/cipher/cbc.go -@@ -15,6 +15,7 @@ import ( - "bytes" - "crypto/internal/fips140/aes" - "crypto/internal/fips140/alias" -+ "crypto/internal/fips140only" - "crypto/subtle" - ) - -@@ -53,6 +54,9 @@ func NewCBCEncrypter(b Block, iv []byte) BlockMode { - if b, ok := b.(*aes.Block); ok { - return aes.NewCBCEncrypter(b, [16]byte(iv)) - } -+ if fips140only.Enabled { -+ panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode") -+ } - if cbc, ok := b.(cbcEncAble); ok { - return cbc.NewCBCEncrypter(iv) - } -@@ -129,6 +133,9 @@ func NewCBCDecrypter(b Block, iv []byte) BlockMode { - if b, ok := b.(*aes.Block); ok { - return aes.NewCBCDecrypter(b, [16]byte(iv)) - } -+ if fips140only.Enabled { -+ panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode") -+ } - if cbc, ok := b.(cbcDecAble); ok { - return cbc.NewCBCDecrypter(iv) - } -diff --git a/src/crypto/cipher/ctr.go b/src/crypto/cipher/ctr.go -index c868635b8a..49512ca5dd 100644 ---- a/src/crypto/cipher/ctr.go -+++ b/src/crypto/cipher/ctr.go -@@ -16,6 +16,7 @@ import ( - "bytes" - "crypto/internal/fips140/aes" - "crypto/internal/fips140/alias" -+ "crypto/internal/fips140only" - "crypto/subtle" - ) - -@@ -41,6 +42,9 @@ func NewCTR(block Block, iv []byte) Stream { - if block, ok := block.(*aes.Block); ok { - return aesCtrWrapper{aes.NewCTR(block, iv)} - } -+ if fips140only.Enabled { -+ panic("crypto/cipher: use of CTR with non-AES ciphers is not allowed in FIPS 140-only mode") -+ } - if ctr, ok := block.(ctrAble); ok { - return ctr.NewCTR(iv) - } -diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go -index 77727aaf96..f682e6b1c6 100644 ---- a/src/crypto/ecdsa/ecdsa.go -+++ b/src/crypto/ecdsa/ecdsa.go -@@ -3,7 +3,7 @@ - // license that can be found in the LICENSE file. - - // Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as --// defined in FIPS 186-5 and SEC 1, Version 2.0. -+// defined in [FIPS 186-5]. - // - // Signatures generated by this package are not deterministic, but entropy is - // mixed with the private key and the message, achieving the same level of -@@ -12,6 +12,8 @@ - // Operations involving private keys are implemented using constant-time - // algorithms, as long as an [elliptic.Curve] returned by [elliptic.P224], - // [elliptic.P256], [elliptic.P384], or [elliptic.P521] is used. -+// -+// [FIPS 186-5]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf - package ecdsa - - import ( -@@ -183,7 +185,7 @@ func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) { - } - - func generateFIPS[P ecdsa.Point[P]](curve elliptic.Curve, c *ecdsa.Curve[P], rand io.Reader) (*PrivateKey, error) { -- if fips140only.Enabled && fips140only.ApprovedRandomReader(rand) { -+ if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) { - return nil, errors.New("crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode") - } - privateKey, err := ecdsa.GenerateKey(c, rand) -diff --git a/src/crypto/fips140/fips140.go b/src/crypto/fips140/fips140.go -index 9fd8fe76e5..41d0d170cf 100644 ---- a/src/crypto/fips140/fips140.go -+++ b/src/crypto/fips140/fips140.go -@@ -26,7 +26,7 @@ func Enabled() bool { - if currentlyEnabled != fips140.Enabled { - panic("crypto/fips140: GODEBUG setting changed after program start") - } -- if fips140.Enabled && !check.Enabled() { -+ if fips140.Enabled && !check.Verified { - panic("crypto/fips140: FIPS 140-3 mode enabled, but integrity check didn't pass") - } - return fips140.Enabled -diff --git a/src/crypto/internal/boring/boring.go b/src/crypto/internal/boring/boring.go -index 90cf1edb75..6dfc6ed5f5 100644 ---- a/src/crypto/internal/boring/boring.go -+++ b/src/crypto/internal/boring/boring.go -@@ -16,6 +16,7 @@ import "C" - import ( - "crypto/internal/boring/sig" - _ "crypto/internal/boring/syso" -+ "crypto/internal/fips140" - "internal/stringslite" - "math/bits" - "unsafe" -@@ -31,6 +32,12 @@ func init() { - sig.BoringCrypto() - } - -+func init() { -+ if fips140.Enabled { -+ panic("boringcrypto: cannot use GODEBUG=fips140 with GOEXPERIMENT=boringcrypto") -+ } -+} -+ - // Unreachable marks code that should be unreachable - // when BoringCrypto is in use. It panics. - func Unreachable() { -diff --git a/src/crypto/internal/cryptotest/allocations.go b/src/crypto/internal/cryptotest/allocations.go -index 0194c2f89d..70055af70b 100644 ---- a/src/crypto/internal/cryptotest/allocations.go -+++ b/src/crypto/internal/cryptotest/allocations.go -@@ -32,6 +32,12 @@ func SkipTestAllocations(t *testing.T) { - t.Skip("skipping allocations test on plan9") - } - -+ // s390x deviates from other assembly implementations and is very hard to -+ // test due to the lack of LUCI builders. See #67307. -+ if runtime.GOARCH == "s390x" { -+ t.Skip("skipping allocations test on s390x") -+ } -+ - // Some APIs rely on inliner and devirtualization to allocate on the stack. - testenv.SkipIfOptimizationOff(t) - } -diff --git a/src/crypto/internal/fips140/aes/aes.go b/src/crypto/internal/fips140/aes/aes.go -index 739f1a3dbe..62f6919eda 100644 ---- a/src/crypto/internal/fips140/aes/aes.go -+++ b/src/crypto/internal/fips140/aes/aes.go -@@ -94,6 +94,8 @@ func newBlockExpanded(c *blockExpanded, key []byte) { - func (c *Block) BlockSize() int { return BlockSize } - - func (c *Block) Encrypt(dst, src []byte) { -+ // AES-ECB is not approved in FIPS 140-3 mode. -+ fips140.RecordNonApproved() - if len(src) < BlockSize { - panic("crypto/aes: input not full block") - } -@@ -103,11 +105,12 @@ func (c *Block) Encrypt(dst, src []byte) { - if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { - panic("crypto/aes: invalid buffer overlap") - } -- fips140.RecordApproved() - encryptBlock(c, dst, src) - } - - func (c *Block) Decrypt(dst, src []byte) { -+ // AES-ECB is not approved in FIPS 140-3 mode. -+ fips140.RecordNonApproved() - if len(src) < BlockSize { - panic("crypto/aes: input not full block") - } -@@ -117,6 +120,12 @@ func (c *Block) Decrypt(dst, src []byte) { - if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { - panic("crypto/aes: invalid buffer overlap") - } -- fips140.RecordApproved() - decryptBlock(c, dst, src) - } -+ -+// EncryptBlockInternal applies the AES encryption function to one block. -+// -+// It is an internal function meant only for the gcm package. -+func EncryptBlockInternal(c *Block, dst, src []byte) { -+ encryptBlock(c, dst, src) -+} -diff --git a/src/crypto/internal/fips140/aes/cbc.go b/src/crypto/internal/fips140/aes/cbc.go -index c7837b9d87..f92af23a2a 100644 ---- a/src/crypto/internal/fips140/aes/cbc.go -+++ b/src/crypto/internal/fips140/aes/cbc.go -@@ -50,7 +50,7 @@ func cryptBlocksEncGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) { - for len(src) > 0 { - // Write the xor to dst, then encrypt in place. - subtle.XORBytes(dst[:BlockSize], src[:BlockSize], iv) -- b.Encrypt(dst[:BlockSize], dst[:BlockSize]) -+ encryptBlock(b, dst[:BlockSize], dst[:BlockSize]) - - // Move to the next block with this block as the next iv. - iv = dst[:BlockSize] -@@ -111,7 +111,7 @@ func cryptBlocksDecGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) { - copy(civ[:], src[start:end]) - - for start >= 0 { -- b.Decrypt(dst[start:end], src[start:end]) -+ decryptBlock(b, dst[start:end], src[start:end]) - - if start > 0 { - subtle.XORBytes(dst[start:end], dst[start:end], src[prev:start]) -diff --git a/src/crypto/internal/fips140/aes/ctr.go b/src/crypto/internal/fips140/aes/ctr.go -index f612034d85..2b0ee44cdd 100644 ---- a/src/crypto/internal/fips140/aes/ctr.go -+++ b/src/crypto/internal/fips140/aes/ctr.go -@@ -132,7 +132,7 @@ func ctrBlocks(b *Block, dst, src []byte, ivlo, ivhi uint64) { - byteorder.BEPutUint64(buf[i:], ivhi) - byteorder.BEPutUint64(buf[i+8:], ivlo) - ivlo, ivhi = add128(ivlo, ivhi, 1) -- b.Encrypt(buf[i:], buf[i:]) -+ encryptBlock(b, buf[i:], buf[i:]) - } - // XOR into buf first, in case src and dst overlap (see above). - subtle.XORBytes(buf, src, buf) -diff --git a/src/crypto/internal/fips140/aes/gcm/cmac.go b/src/crypto/internal/fips140/aes/gcm/cmac.go -index e0a9dc43de..3a979a5c70 100644 ---- a/src/crypto/internal/fips140/aes/gcm/cmac.go -+++ b/src/crypto/internal/fips140/aes/gcm/cmac.go -@@ -28,7 +28,7 @@ func NewCMAC(b *aes.Block) *CMAC { - } - - func (c *CMAC) deriveSubkeys() { -- c.b.Encrypt(c.k1[:], c.k1[:]) -+ aes.EncryptBlockInternal(&c.b, c.k1[:], c.k1[:]) - msb := shiftLeft(&c.k1) - c.k1[len(c.k1)-1] ^= msb * 0b10000111 - -@@ -45,7 +45,7 @@ func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte { - // Special-cased as a single empty partial final block. - x = c.k2 - x[len(m)] ^= 0b10000000 -- c.b.Encrypt(x[:], x[:]) -+ aes.EncryptBlockInternal(&c.b, x[:], x[:]) - return x - } - for len(m) >= aes.BlockSize { -@@ -54,7 +54,7 @@ func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte { - // Final complete block. - subtle.XORBytes(x[:], c.k1[:], x[:]) - } -- c.b.Encrypt(x[:], x[:]) -+ aes.EncryptBlockInternal(&c.b, x[:], x[:]) - m = m[aes.BlockSize:] - } - if len(m) > 0 { -@@ -62,7 +62,7 @@ func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte { - subtle.XORBytes(x[:], m, x[:]) - subtle.XORBytes(x[:], c.k2[:], x[:]) - x[len(m)] ^= 0b10000000 -- c.b.Encrypt(x[:], x[:]) -+ aes.EncryptBlockInternal(&c.b, x[:], x[:]) - } - return x - } -diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_asm.go b/src/crypto/internal/fips140/aes/gcm/gcm_asm.go -index d513f77a2f..7924e457de 100644 ---- a/src/crypto/internal/fips140/aes/gcm/gcm_asm.go -+++ b/src/crypto/internal/fips140/aes/gcm/gcm_asm.go -@@ -81,7 +81,7 @@ func seal(out []byte, g *GCM, nonce, plaintext, data []byte) { - gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) - } - -- g.cipher.Encrypt(tagMask[:], counter[:]) -+ aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) - - var tagOut [gcmTagSize]byte - gcmAesData(&g.productTable, data, &tagOut) -@@ -114,7 +114,7 @@ func open(out []byte, g *GCM, nonce, ciphertext, data []byte) error { - gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) - } - -- g.cipher.Encrypt(tagMask[:], counter[:]) -+ aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) - - var expectedTag [gcmTagSize]byte - gcmAesData(&g.productTable, data, &expectedTag) -diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_generic.go b/src/crypto/internal/fips140/aes/gcm/gcm_generic.go -index 778392661d..385955ed77 100644 ---- a/src/crypto/internal/fips140/aes/gcm/gcm_generic.go -+++ b/src/crypto/internal/fips140/aes/gcm/gcm_generic.go -@@ -12,7 +12,7 @@ import ( - - func sealGeneric(out []byte, g *GCM, nonce, plaintext, additionalData []byte) { - var H, counter, tagMask [gcmBlockSize]byte -- g.cipher.Encrypt(H[:], H[:]) -+ aes.EncryptBlockInternal(&g.cipher, H[:], H[:]) - deriveCounterGeneric(&H, &counter, nonce) - gcmCounterCryptGeneric(&g.cipher, tagMask[:], tagMask[:], &counter) - -@@ -25,7 +25,7 @@ func sealGeneric(out []byte, g *GCM, nonce, plaintext, additionalData []byte) { - - func openGeneric(out []byte, g *GCM, nonce, ciphertext, additionalData []byte) error { - var H, counter, tagMask [gcmBlockSize]byte -- g.cipher.Encrypt(H[:], H[:]) -+ aes.EncryptBlockInternal(&g.cipher, H[:], H[:]) - deriveCounterGeneric(&H, &counter, nonce) - gcmCounterCryptGeneric(&g.cipher, tagMask[:], tagMask[:], &counter) - -@@ -70,7 +70,7 @@ func gcmCounterCryptGeneric(b *aes.Block, out, src []byte, counter *[gcmBlockSiz - var mask [gcmBlockSize]byte - - for len(src) >= gcmBlockSize { -- b.Encrypt(mask[:], counter[:]) -+ aes.EncryptBlockInternal(b, mask[:], counter[:]) - gcmInc32(counter) - - subtle.XORBytes(out, src, mask[:]) -@@ -79,7 +79,7 @@ func gcmCounterCryptGeneric(b *aes.Block, out, src []byte, counter *[gcmBlockSiz - } - - if len(src) > 0 { -- b.Encrypt(mask[:], counter[:]) -+ aes.EncryptBlockInternal(b, mask[:], counter[:]) - gcmInc32(counter) - subtle.XORBytes(out, src, mask[:]) - } -diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go b/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go -index 5084835e88..8d44c75745 100644 ---- a/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go -+++ b/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go -@@ -51,7 +51,7 @@ func initGCM(g *GCM) { - } - - hle := make([]byte, gcmBlockSize) -- g.cipher.Encrypt(hle, hle) -+ aes.EncryptBlockInternal(&g.cipher, hle, hle) - - // Reverse the bytes in each 8 byte chunk - // Load little endian, store big endian -@@ -133,7 +133,7 @@ func seal(out []byte, g *GCM, nonce, plaintext, data []byte) { - var counter, tagMask [gcmBlockSize]byte - deriveCounter(&counter, nonce, &g.productTable) - -- g.cipher.Encrypt(tagMask[:], counter[:]) -+ aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) - gcmInc32(&counter) - - counterCrypt(&g.cipher, out, plaintext, &counter) -@@ -151,7 +151,7 @@ func open(out []byte, g *GCM, nonce, ciphertext, data []byte) error { - var counter, tagMask [gcmBlockSize]byte - deriveCounter(&counter, nonce, &g.productTable) - -- g.cipher.Encrypt(tagMask[:], counter[:]) -+ aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) - gcmInc32(&counter) - - var expectedTag [gcmTagSize]byte -diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go b/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go -index 6d88e18240..526f3f9d4a 100644 ---- a/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go -+++ b/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go -@@ -55,7 +55,7 @@ func initGCM(g *GCM) { - return - } - // Note that hashKey is also used in the KMA codepath to hash large nonces. -- g.cipher.Encrypt(g.hashKey[:], g.hashKey[:]) -+ aes.EncryptBlockInternal(&g.cipher, g.hashKey[:], g.hashKey[:]) - } - - // ghashAsm uses the GHASH algorithm to hash data with the given key. The initial -@@ -115,7 +115,7 @@ func counterCrypt(g *GCM, dst, src []byte, cnt *[gcmBlockSize]byte) { - } - if len(src) > 0 { - var x [16]byte -- g.cipher.Encrypt(x[:], cnt[:]) -+ aes.EncryptBlockInternal(&g.cipher, x[:], cnt[:]) - for i := range src { - dst[i] = src[i] ^ x[i] - } -diff --git a/src/crypto/internal/fips140/check/asan.go b/src/crypto/internal/fips140/asan.go -similarity index 92% -rename from src/crypto/internal/fips140/check/asan.go -rename to src/crypto/internal/fips140/asan.go -index 2c78348354..af8f24df81 100644 ---- a/src/crypto/internal/fips140/check/asan.go -+++ b/src/crypto/internal/fips140/asan.go -@@ -4,6 +4,6 @@ - - //go:build asan - --package check -+package fips140 - - const asanEnabled = true -diff --git a/src/crypto/internal/fips140/bigmod/nat.go b/src/crypto/internal/fips140/bigmod/nat.go -index 2f17f896b3..6757cccd02 100644 ---- a/src/crypto/internal/fips140/bigmod/nat.go -+++ b/src/crypto/internal/fips140/bigmod/nat.go -@@ -134,6 +134,13 @@ func (x *Nat) set(y *Nat) *Nat { - return x - } - -+// Bits returns x as a little-endian slice of uint. The length of the slice -+// matches the announced length of x. The result and x share the same underlying -+// array. -+func (x *Nat) Bits() []uint { -+ return x.limbs -+} -+ - // Bytes returns x as a zero-extended big-endian byte slice. The size of the - // slice will match the size of m. - // -@@ -1058,6 +1065,34 @@ func (out *Nat) ExpShortVarTime(x *Nat, e uint, m *Modulus) *Nat { - // - //go:norace - func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { -+ u, A, err := extendedGCD(a, m.nat) -+ if err != nil { -+ return x, false -+ } -+ if u.IsOne() == no { -+ return x, false -+ } -+ return x.set(A), true -+} -+ -+// GCDVarTime calculates x = GCD(a, b) where at least one of a or b is odd, and -+// both are non-zero. If GCDVarTime returns an error, x is not modified. -+// -+// The output will be resized to the size of the larger of a and b. -+func (x *Nat) GCDVarTime(a, b *Nat) (*Nat, error) { -+ u, _, err := extendedGCD(a, b) -+ if err != nil { -+ return nil, err -+ } -+ return x.set(u), nil -+} -+ -+// extendedGCD computes u and A such that a = GCD(a, m) and u = A*a - B*m. -+// -+// u will have the size of the larger of a and m, and A will have the size of m. -+// -+// It is an error if either a or m is zero, or if they are both even. -+func extendedGCD(a, m *Nat) (u, A *Nat, err error) { - // This is the extended binary GCD algorithm described in the Handbook of - // Applied Cryptography, Algorithm 14.61, adapted by BoringSSL to bound - // coefficients and avoid negative numbers. For more details and proof of -@@ -1068,7 +1103,7 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { - // 1. Negate [B] and [C] so they are positive. The invariant now involves a - // subtraction. - // 2. If step 2 (both [x] and [y] are even) runs, abort immediately. This -- // algorithm only cares about [x] and [y] relatively prime. -+ // case needs to be handled by the caller. - // 3. Subtract copies of [x] and [y] as needed in step 6 (both [u] and [v] - // are odd) so coefficients stay in bounds. - // 4. Replace the [u >= v] check with [u > v]. This changes the end -@@ -1082,21 +1117,21 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { - // - // Note this algorithm does not handle either input being zero. - -- if a.IsZero() == yes { -- return x, false -+ if a.IsZero() == yes || m.IsZero() == yes { -+ return nil, nil, errors.New("extendedGCD: a or m is zero") - } -- if a.IsOdd() == no && !m.odd { -- // a and m are not coprime, as they are both even. -- return x, false -+ if a.IsOdd() == no && m.IsOdd() == no { -+ return nil, nil, errors.New("extendedGCD: both a and m are even") - } - -- u := NewNat().set(a).ExpandFor(m) -- v := m.Nat() -+ size := max(len(a.limbs), len(m.limbs)) -+ u = NewNat().set(a).expand(size) -+ v := NewNat().set(m).expand(size) - -- A := NewNat().reset(len(m.nat.limbs)) -+ A = NewNat().reset(len(m.limbs)) - A.limbs[0] = 1 - B := NewNat().reset(len(a.limbs)) -- C := NewNat().reset(len(m.nat.limbs)) -+ C := NewNat().reset(len(m.limbs)) - D := NewNat().reset(len(a.limbs)) - D.limbs[0] = 1 - -@@ -1119,11 +1154,11 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { - if u.IsOdd() == yes && v.IsOdd() == yes { - if v.cmpGeq(u) == no { - u.sub(v) -- A.Add(C, m) -+ A.Add(C, &Modulus{nat: m}) - B.Add(D, &Modulus{nat: a}) - } else { - v.sub(u) -- C.Add(A, m) -+ C.Add(A, &Modulus{nat: m}) - D.Add(B, &Modulus{nat: a}) - } - } -@@ -1137,7 +1172,7 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { - if u.IsOdd() == no { - rshift1(u, 0) - if A.IsOdd() == yes || B.IsOdd() == yes { -- rshift1(A, A.add(m.nat)) -+ rshift1(A, A.add(m)) - rshift1(B, B.add(a)) - } else { - rshift1(A, 0) -@@ -1146,7 +1181,7 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { - } else { // v.IsOdd() == no - rshift1(v, 0) - if C.IsOdd() == yes || D.IsOdd() == yes { -- rshift1(C, C.add(m.nat)) -+ rshift1(C, C.add(m)) - rshift1(D, D.add(a)) - } else { - rshift1(C, 0) -@@ -1155,10 +1190,7 @@ func (x *Nat) InverseVarTime(a *Nat, m *Modulus) (*Nat, bool) { - } - - if v.IsZero() == yes { -- if u.IsOne() == no { -- return x, false -- } -- return x.set(A), true -+ return u, A, nil - } - } - } -@@ -1177,3 +1209,20 @@ func rshift1(a *Nat, carry uint) { - } - } - } -+ -+// DivShortVarTime calculates x = x / y and returns the remainder. -+// -+// It panics if y is zero. -+// -+//go:norace -+func (x *Nat) DivShortVarTime(y uint) uint { -+ if y == 0 { -+ panic("bigmod: division by zero") -+ } -+ -+ var r uint -+ for i := len(x.limbs) - 1; i >= 0; i-- { -+ x.limbs[i], r = bits.Div(r, x.limbs[i], y) -+ } -+ return r -+} -diff --git a/src/crypto/internal/fips140/boring.go b/src/crypto/internal/fips140/boring.go -new file mode 100644 -index 0000000000..d627bc6890 ---- /dev/null -+++ b/src/crypto/internal/fips140/boring.go -@@ -0,0 +1,10 @@ -+// Copyright 2024 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Keep in sync with notboring.go and crypto/internal/boring/boring.go. -+//go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan && cgo -+ -+package fips140 -+ -+const boringEnabled = true -diff --git a/src/crypto/internal/fips140/check/check.go b/src/crypto/internal/fips140/check/check.go -index ff61b80cb3..f8a5d7a41e 100644 ---- a/src/crypto/internal/fips140/check/check.go -+++ b/src/crypto/internal/fips140/check/check.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --// Package check implements the FIPS-140 load-time code+data verification. -+// Package check implements the FIPS 140 load-time code+data verification. - // Every FIPS package providing cryptographic functionality except hmac and sha256 - // must import crypto/internal/fips140/check, so that the verification happens - // before initialization of package global variables. -@@ -13,37 +13,18 @@ - package check - - import ( -+ "crypto/internal/fips140" - "crypto/internal/fips140/hmac" - "crypto/internal/fips140/sha256" - "crypto/internal/fips140deps/byteorder" - "crypto/internal/fips140deps/godebug" - "io" -- "runtime" - "unsafe" - ) - --// Enabled reports whether verification was enabled. --// If Enabled returns true, then verification succeeded, --// because if it failed the binary would have panicked at init time. --func Enabled() bool { -- return enabled --} -- --var enabled bool // set when verification is enabled --var Verified bool // set when verification succeeds, for testing -- --// Supported reports whether the current GOOS/GOARCH is Supported at all. --func Supported() bool { -- // See cmd/internal/obj/fips.go's EnableFIPS for commentary. -- switch { -- case runtime.GOARCH == "wasm", -- runtime.GOOS == "windows" && runtime.GOARCH == "386", -- runtime.GOOS == "windows" && runtime.GOARCH == "arm", -- runtime.GOOS == "aix": -- return false -- } -- return true --} -+// Verified is set when verification succeeded. It can be expected to always be -+// true when [fips140.Enabled] is true, or init would have panicked. -+var Verified bool - - // Linkinfo holds the go:fipsinfo symbol prepared by the linker. - // See cmd/link/internal/ld/fips.go for details. -@@ -71,32 +52,12 @@ const fipsMagic = " Go fipsinfo \xff\x00" - var zeroSum [32]byte - - func init() { -- v := godebug.Value("#fips140") -- enabled = v != "" && v != "off" -- if !enabled { -+ if !fips140.Enabled { - return - } - -- if asanEnabled { -- // ASAN disapproves of reading swaths of global memory below. -- // One option would be to expose runtime.asanunpoison through -- // crypto/internal/fips140deps and then call it to unpoison the range -- // before reading it, but it is unclear whether that would then cause -- // false negatives. For now, FIPS+ASAN doesn't need to work. -- // If this is made to work, also re-enable the test in check_test.go -- // and in cmd/dist/test.go. -- panic("fips140: cannot verify in asan mode") -- } -- -- switch v { -- case "on", "only", "debug": -- // ok -- default: -- panic("fips140: unknown GODEBUG setting fips140=" + v) -- } -- -- if !Supported() { -- panic("fips140: unavailable on " + runtime.GOOS + "-" + runtime.GOARCH) -+ if err := fips140.Supported(); err != nil { -+ panic("fips140: " + err.Error()) - } - - if Linkinfo.Magic[0] != 0xff || string(Linkinfo.Magic[1:]) != fipsMagic || Linkinfo.Sum == zeroSum { -@@ -132,7 +93,14 @@ func init() { - panic("fips140: verification mismatch") - } - -- if v == "debug" { -+ // "The temporary value(s) generated during the integrity test of the -+ // module’s software or firmware shall [05.10] be zeroised from the module -+ // upon completion of the integrity test" -+ clear(sum) -+ clear(nbuf[:]) -+ h.Reset() -+ -+ if godebug.Value("#fips140") == "debug" { - println("fips140: verified code+data") - } - -diff --git a/src/crypto/internal/fips140/drbg/rand.go b/src/crypto/internal/fips140/drbg/rand.go -index 967fb0673e..e7ab19a4cf 100644 ---- a/src/crypto/internal/fips140/drbg/rand.go -+++ b/src/crypto/internal/fips140/drbg/rand.go -@@ -13,8 +13,15 @@ import ( - "sync" - ) - --var mu sync.Mutex --var drbg *Counter -+var drbgs = sync.Pool{ -+ New: func() any { -+ var c *Counter -+ entropy.Depleted(func(seed *[48]byte) { -+ c = NewCounter(seed) -+ }) -+ return c -+ }, -+} - - // Read fills b with cryptographically secure random bytes. In FIPS mode, it - // uses an SP 800-90A Rev. 1 Deterministic Random Bit Generator (DRBG). -@@ -33,14 +40,8 @@ func Read(b []byte) { - additionalInput := new([SeedSize]byte) - sysrand.Read(additionalInput[:16]) - -- mu.Lock() -- defer mu.Unlock() -- -- if drbg == nil { -- entropy.Depleted(func(seed *[48]byte) { -- drbg = NewCounter(seed) -- }) -- } -+ drbg := drbgs.Get().(*Counter) -+ defer drbgs.Put(drbg) - - for len(b) > 0 { - size := min(len(b), maxRequestSize) -diff --git a/src/crypto/internal/fips140/drbg/rand_test.go b/src/crypto/internal/fips140/drbg/rand_test.go -new file mode 100644 -index 0000000000..945ebde933 ---- /dev/null -+++ b/src/crypto/internal/fips140/drbg/rand_test.go -@@ -0,0 +1,27 @@ -+// Copyright 2025 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package drbg -+ -+import ( -+ "crypto/internal/fips140" -+ "testing" -+) -+ -+func BenchmarkDBRG(b *testing.B) { -+ old := fips140.Enabled -+ defer func() { -+ fips140.Enabled = old -+ }() -+ fips140.Enabled = true -+ -+ const N = 64 -+ b.SetBytes(N) -+ b.RunParallel(func(pb *testing.PB) { -+ buf := make([]byte, N) -+ for pb.Next() { -+ Read(buf) -+ } -+ }) -+} -diff --git a/src/crypto/internal/fips140/ecdsa/ecdsa.go b/src/crypto/internal/fips140/ecdsa/ecdsa.go -index 9459b03de7..11389e8210 100644 ---- a/src/crypto/internal/fips140/ecdsa/ecdsa.go -+++ b/src/crypto/internal/fips140/ecdsa/ecdsa.go -@@ -21,7 +21,7 @@ import ( - - type PrivateKey struct { - pub PublicKey -- d []byte // bigmod.(*Nat).Bytes output (fixed length) -+ d []byte // bigmod.(*Nat).Bytes output (same length as the curve order) - } - - func (priv *PrivateKey) Bytes() []byte { -@@ -262,7 +262,7 @@ func randomPoint[P Point[P]](c *Curve[P], generate func([]byte) error) (k *bigmo - var testingOnlyRejectionSamplingLooped func() - - // Signature is an ECDSA signature, where r and s are represented as big-endian --// fixed-length byte slices. -+// byte slices of the same length as the curve order. - type Signature struct { - R, S []byte - } -diff --git a/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go b/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go -index 01379f998f..271a35897f 100644 ---- a/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go -+++ b/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go -@@ -47,15 +47,34 @@ func canUseKDSA(c curveID) (functionCode uint64, blockSize int, ok bool) { - case p384: - return 2, 48, true - case p521: -+ // Note that the block size doesn't match the field size for P-521. - return 3, 80, true - } - return 0, 0, false // A mismatch - } - --func hashToBytes[P Point[P]](c *Curve[P], dst, hash []byte) { -+func hashToBytes[P Point[P]](c *Curve[P], hash []byte) []byte { - e := bigmod.NewNat() - hashToNat(c, e, hash) -- copy(dst, e.Bytes(c.N)) -+ return e.Bytes(c.N) -+} -+ -+func appendBlock(p []byte, blocksize int, b []byte) []byte { -+ if len(b) > blocksize { -+ panic("ecdsa: internal error: appendBlock input larger than block") -+ } -+ padding := blocksize - len(b) -+ p = append(p, make([]byte, padding)...) -+ return append(p, b...) -+} -+ -+func trimBlock(p []byte, size int) ([]byte, error) { -+ for _, b := range p[:len(p)-size] { -+ if b != 0 { -+ return nil, errors.New("ecdsa: internal error: KDSA produced invalid signature") -+ } -+ } -+ return p[len(p)-size:], nil - } - - func sign[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte) (*Signature, error) { -@@ -95,17 +114,27 @@ func sign[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte - - // Copy content into the parameter block. In the sign case, - // we copy hashed message, private key and random number into -- // the parameter block. -- hashToBytes(c, params[2*blockSize:3*blockSize], hash) -- copy(params[3*blockSize+blockSize-len(priv.d):], priv.d) -- copy(params[4*blockSize:5*blockSize], k.Bytes(c.N)) -+ // the parameter block. We skip the signature slots. -+ p := params[:2*blockSize] -+ p = appendBlock(p, blockSize, hashToBytes(c, hash)) -+ p = appendBlock(p, blockSize, priv.d) -+ p = appendBlock(p, blockSize, k.Bytes(c.N)) - // Convert verify function code into a sign function code by adding 8. - // We also need to set the 'deterministic' bit in the function code, by - // adding 128, in order to stop the instruction using its own random number - // generator in addition to the random number we supply. - switch kdsa(functionCode+136, ¶ms) { - case 0: // success -- return &Signature{R: params[:blockSize], S: params[blockSize : 2*blockSize]}, nil -+ elementSize := (c.N.BitLen() + 7) / 8 -+ r, err := trimBlock(params[:blockSize], elementSize) -+ if err != nil { -+ return nil, err -+ } -+ s, err := trimBlock(params[blockSize:2*blockSize], elementSize) -+ if err != nil { -+ return nil, err -+ } -+ return &Signature{R: r, S: s}, nil - case 1: // error - return nil, errors.New("zero parameter") - case 2: // retry -@@ -149,10 +178,12 @@ func verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature - // Copy content into the parameter block. In the verify case, - // we copy signature (r), signature(s), hashed message, public key x component, - // and public key y component into the parameter block. -- copy(params[0*blockSize+blockSize-len(r):], r) -- copy(params[1*blockSize+blockSize-len(s):], s) -- hashToBytes(c, params[2*blockSize:3*blockSize], hash) -- copy(params[3*blockSize:5*blockSize], pub.q[1:]) // strip 0x04 prefix -+ p := params[:0] -+ p = appendBlock(p, blockSize, r) -+ p = appendBlock(p, blockSize, s) -+ p = appendBlock(p, blockSize, hashToBytes(c, hash)) -+ p = appendBlock(p, blockSize, pub.q[1:1+len(pub.q)/2]) -+ p = appendBlock(p, blockSize, pub.q[1+len(pub.q)/2:]) - if kdsa(functionCode, ¶ms) != 0 { - return errors.New("invalid signature") - } -diff --git a/src/crypto/internal/fips140/fips140.go b/src/crypto/internal/fips140/fips140.go -index cec9d13e35..c7b167b82a 100644 ---- a/src/crypto/internal/fips140/fips140.go -+++ b/src/crypto/internal/fips140/fips140.go -@@ -4,18 +4,64 @@ - - package fips140 - --import "crypto/internal/fips140deps/godebug" -+import ( -+ "crypto/internal/fips140deps/godebug" -+ "errors" -+ "runtime" -+) - - var Enabled bool - - var debug bool - - func init() { -- switch godebug.Value("#fips140") { -+ v := godebug.Value("#fips140") -+ switch v { - case "on", "only": - Enabled = true - case "debug": - Enabled = true - debug = true -+ case "off", "": -+ default: -+ panic("fips140: unknown GODEBUG setting fips140=" + v) - } - } -+ -+// Supported returns an error if FIPS 140-3 mode can't be enabled. -+func Supported() error { -+ // Keep this in sync with fipsSupported in cmd/dist/test.go. -+ -+ // ASAN disapproves of reading swaths of global memory in fips140/check. -+ // One option would be to expose runtime.asanunpoison through -+ // crypto/internal/fips140deps and then call it to unpoison the range -+ // before reading it, but it is unclear whether that would then cause -+ // false negatives. For now, FIPS+ASAN doesn't need to work. -+ if asanEnabled { -+ return errors.New("FIPS 140-3 mode is incompatible with ASAN") -+ } -+ -+ // See EnableFIPS in cmd/internal/obj/fips.go for commentary. -+ switch { -+ case runtime.GOARCH == "wasm", -+ runtime.GOOS == "windows" && runtime.GOARCH == "386", -+ runtime.GOOS == "windows" && runtime.GOARCH == "arm", -+ runtime.GOOS == "openbsd", // due to -fexecute-only, see #70880 -+ runtime.GOOS == "aix": -+ return errors.New("FIPS 140-3 mode is not supported on " + runtime.GOOS + "-" + runtime.GOARCH) -+ } -+ -+ if boringEnabled { -+ return errors.New("FIPS 140-3 mode is incompatible with GOEXPERIMENT=boringcrypto") -+ } -+ -+ return nil -+} -+ -+func Name() string { -+ return "Go Cryptographic Module" -+} -+ -+func Version() string { -+ return "v1.0" -+} -diff --git a/src/crypto/internal/fips140/mlkem/cast.go b/src/crypto/internal/fips140/mlkem/cast.go -index d3ae84ec3f..a432d1fdab 100644 ---- a/src/crypto/internal/fips140/mlkem/cast.go -+++ b/src/crypto/internal/fips140/mlkem/cast.go -@@ -40,7 +40,7 @@ func init() { - dk := &DecapsulationKey768{} - kemKeyGen(dk, d, z) - ek := dk.EncapsulationKey() -- c, Ke := ek.EncapsulateInternal(m) -+ Ke, c := ek.EncapsulateInternal(m) - Kd, err := dk.Decapsulate(c) - if err != nil { - return err -diff --git a/src/crypto/internal/fips140/mlkem/mlkem1024.go b/src/crypto/internal/fips140/mlkem/mlkem1024.go -index 5aa3c69243..c924c38293 100644 ---- a/src/crypto/internal/fips140/mlkem/mlkem1024.go -+++ b/src/crypto/internal/fips140/mlkem/mlkem1024.go -@@ -189,7 +189,7 @@ func kemKeyGen1024(dk *DecapsulationKey1024, d, z *[32]byte) { - // the first operational use (if not exported before the first use)." - func kemPCT1024(dk *DecapsulationKey1024) error { - ek := dk.EncapsulationKey() -- c, K := ek.Encapsulate() -+ K, c := ek.Encapsulate() - K1, err := dk.Decapsulate(c) - if err != nil { - return err -@@ -204,13 +204,13 @@ func kemPCT1024(dk *DecapsulationKey1024) error { - // encapsulation key, drawing random bytes from a DRBG. - // - // The shared key must be kept secret. --func (ek *EncapsulationKey1024) Encapsulate() (ciphertext, sharedKey []byte) { -+func (ek *EncapsulationKey1024) Encapsulate() (sharedKey, ciphertext []byte) { - // The actual logic is in a separate function to outline this allocation. - var cc [CiphertextSize1024]byte - return ek.encapsulate(&cc) - } - --func (ek *EncapsulationKey1024) encapsulate(cc *[CiphertextSize1024]byte) (ciphertext, sharedKey []byte) { -+func (ek *EncapsulationKey1024) encapsulate(cc *[CiphertextSize1024]byte) (sharedKey, ciphertext []byte) { - var m [messageSize]byte - drbg.Read(m[:]) - // Note that the modulus check (step 2 of the encapsulation key check from -@@ -221,7 +221,7 @@ func (ek *EncapsulationKey1024) encapsulate(cc *[CiphertextSize1024]byte) (ciphe - - // EncapsulateInternal is a derandomized version of Encapsulate, exclusively for - // use in tests. --func (ek *EncapsulationKey1024) EncapsulateInternal(m *[32]byte) (ciphertext, sharedKey []byte) { -+func (ek *EncapsulationKey1024) EncapsulateInternal(m *[32]byte) (sharedKey, ciphertext []byte) { - cc := &[CiphertextSize1024]byte{} - return kemEncaps1024(cc, ek, m) - } -@@ -229,14 +229,14 @@ func (ek *EncapsulationKey1024) EncapsulateInternal(m *[32]byte) (ciphertext, sh - // kemEncaps1024 generates a shared key and an associated ciphertext. - // - // It implements ML-KEM.Encaps_internal according to FIPS 203, Algorithm 17. --func kemEncaps1024(cc *[CiphertextSize1024]byte, ek *EncapsulationKey1024, m *[messageSize]byte) (c, K []byte) { -+func kemEncaps1024(cc *[CiphertextSize1024]byte, ek *EncapsulationKey1024, m *[messageSize]byte) (K, c []byte) { - g := sha3.New512() - g.Write(m[:]) - g.Write(ek.h[:]) - G := g.Sum(nil) - K, r := G[:SharedKeySize], G[SharedKeySize:] - c = pkeEncrypt1024(cc, &ek.encryptionKey1024, m, r) -- return c, K -+ return K, c - } - - // NewEncapsulationKey1024 parses an encapsulation key from its encoded form. -diff --git a/src/crypto/internal/fips140/mlkem/mlkem768.go b/src/crypto/internal/fips140/mlkem/mlkem768.go -index 0c91ceadc4..2c1cb5c33f 100644 ---- a/src/crypto/internal/fips140/mlkem/mlkem768.go -+++ b/src/crypto/internal/fips140/mlkem/mlkem768.go -@@ -246,7 +246,7 @@ func kemKeyGen(dk *DecapsulationKey768, d, z *[32]byte) { - // the first operational use (if not exported before the first use)." - func kemPCT(dk *DecapsulationKey768) error { - ek := dk.EncapsulationKey() -- c, K := ek.Encapsulate() -+ K, c := ek.Encapsulate() - K1, err := dk.Decapsulate(c) - if err != nil { - return err -@@ -261,13 +261,13 @@ func kemPCT(dk *DecapsulationKey768) error { - // encapsulation key, drawing random bytes from a DRBG. - // - // The shared key must be kept secret. --func (ek *EncapsulationKey768) Encapsulate() (ciphertext, sharedKey []byte) { -+func (ek *EncapsulationKey768) Encapsulate() (sharedKey, ciphertext []byte) { - // The actual logic is in a separate function to outline this allocation. - var cc [CiphertextSize768]byte - return ek.encapsulate(&cc) - } - --func (ek *EncapsulationKey768) encapsulate(cc *[CiphertextSize768]byte) (ciphertext, sharedKey []byte) { -+func (ek *EncapsulationKey768) encapsulate(cc *[CiphertextSize768]byte) (sharedKey, ciphertext []byte) { - var m [messageSize]byte - drbg.Read(m[:]) - // Note that the modulus check (step 2 of the encapsulation key check from -@@ -278,7 +278,7 @@ func (ek *EncapsulationKey768) encapsulate(cc *[CiphertextSize768]byte) (ciphert - - // EncapsulateInternal is a derandomized version of Encapsulate, exclusively for - // use in tests. --func (ek *EncapsulationKey768) EncapsulateInternal(m *[32]byte) (ciphertext, sharedKey []byte) { -+func (ek *EncapsulationKey768) EncapsulateInternal(m *[32]byte) (sharedKey, ciphertext []byte) { - cc := &[CiphertextSize768]byte{} - return kemEncaps(cc, ek, m) - } -@@ -286,14 +286,14 @@ func (ek *EncapsulationKey768) EncapsulateInternal(m *[32]byte) (ciphertext, sha - // kemEncaps generates a shared key and an associated ciphertext. - // - // It implements ML-KEM.Encaps_internal according to FIPS 203, Algorithm 17. --func kemEncaps(cc *[CiphertextSize768]byte, ek *EncapsulationKey768, m *[messageSize]byte) (c, K []byte) { -+func kemEncaps(cc *[CiphertextSize768]byte, ek *EncapsulationKey768, m *[messageSize]byte) (K, c []byte) { - g := sha3.New512() - g.Write(m[:]) - g.Write(ek.h[:]) - G := g.Sum(nil) - K, r := G[:SharedKeySize], G[SharedKeySize:] - c = pkeEncrypt(cc, &ek.encryptionKey, m, r) -- return c, K -+ return K, c - } - - // NewEncapsulationKey768 parses an encapsulation key from its encoded form. -diff --git a/src/crypto/internal/fips140/check/noasan.go b/src/crypto/internal/fips140/notasan.go -similarity index 92% -rename from src/crypto/internal/fips140/check/noasan.go -rename to src/crypto/internal/fips140/notasan.go -index 876d726f98..639d419ef9 100644 ---- a/src/crypto/internal/fips140/check/noasan.go -+++ b/src/crypto/internal/fips140/notasan.go -@@ -4,6 +4,6 @@ - - //go:build !asan - --package check -+package fips140 - - const asanEnabled = false -diff --git a/src/crypto/internal/fips140/notboring.go b/src/crypto/internal/fips140/notboring.go -new file mode 100644 -index 0000000000..681521c687 ---- /dev/null -+++ b/src/crypto/internal/fips140/notboring.go -@@ -0,0 +1,9 @@ -+// Copyright 2024 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build !(boringcrypto && linux && (amd64 || arm64) && !android && !msan && cgo) -+ -+package fips140 -+ -+const boringEnabled = false -diff --git a/src/crypto/internal/fips140/rsa/keygen.go b/src/crypto/internal/fips140/rsa/keygen.go -index df76772ef5..658eb9ab24 100644 ---- a/src/crypto/internal/fips140/rsa/keygen.go -+++ b/src/crypto/internal/fips140/rsa/keygen.go -@@ -13,9 +13,9 @@ import ( - ) - - // GenerateKey generates a new RSA key pair of the given bit size. --// bits must be at least 128. -+// bits must be at least 32. - func GenerateKey(rand io.Reader, bits int) (*PrivateKey, error) { -- if bits < 128 { -+ if bits < 32 { - return nil, errors.New("rsa: key too small") - } - fips140.RecordApproved() -@@ -54,23 +54,42 @@ func GenerateKey(rand io.Reader, bits int) (*PrivateKey, error) { - return nil, errors.New("rsa: internal error: modulus size incorrect") - } - -- φ, err := bigmod.NewModulusProduct(P.Nat().SubOne(P).Bytes(P), -- Q.Nat().SubOne(Q).Bytes(Q)) -+ // d can be safely computed as e⁻¹ mod φ(N) where φ(N) = (p-1)(q-1), and -+ // indeed that's what both the original RSA paper and the pre-FIPS -+ // crypto/rsa implementation did. -+ // -+ // However, FIPS 186-5, A.1.1(3) requires computing it as e⁻¹ mod λ(N) -+ // where λ(N) = lcm(p-1, q-1). -+ // -+ // This makes d smaller by 1.5 bits on average, which is irrelevant both -+ // because we exclusively use the CRT for private operations and because -+ // we use constant time windowed exponentiation. On the other hand, it -+ // requires computing a GCD of two values that are not coprime, and then -+ // a division, both complex variable-time operations. -+ λ, err := totient(P, Q) -+ if err == errDivisorTooLarge { -+ // The divisor is too large, try again with different primes. -+ continue -+ } - if err != nil { - return nil, err - } - - e := bigmod.NewNat().SetUint(65537) -- d, ok := bigmod.NewNat().InverseVarTime(e, φ) -+ d, ok := bigmod.NewNat().InverseVarTime(e, λ) - if !ok { -- // This checks that GCD(e, (p-1)(q-1)) = 1, which is equivalent -+ // This checks that GCD(e, lcm(p-1, q-1)) = 1, which is equivalent - // to checking GCD(e, p-1) = 1 and GCD(e, q-1) = 1 separately in - // FIPS 186-5, Appendix A.1.3, steps 4.5 and 5.6. -+ // -+ // We waste a prime by retrying the whole process, since 65537 is -+ // probably only a factor of one of p-1 or q-1, but the probability -+ // of this check failing is only 1/65537, so it doesn't matter. - continue - } - -- if e.ExpandFor(φ).Mul(d, φ).IsOne() == 0 { -- return nil, errors.New("rsa: internal error: e*d != 1 mod φ(N)") -+ if e.ExpandFor(λ).Mul(d, λ).IsOne() == 0 { -+ return nil, errors.New("rsa: internal error: e*d != 1 mod λ(N)") - } - - // FIPS 186-5, A.1.1(3) requires checking that d > 2^(nlen / 2). -@@ -90,11 +109,57 @@ func GenerateKey(rand io.Reader, bits int) (*PrivateKey, error) { - } - } - -+// errDivisorTooLarge is returned by [totient] when gcd(p-1, q-1) is too large. -+var errDivisorTooLarge = errors.New("divisor too large") -+ -+// totient computes the Carmichael totient function λ(N) = lcm(p-1, q-1). -+func totient(p, q *bigmod.Modulus) (*bigmod.Modulus, error) { -+ a, b := p.Nat().SubOne(p), q.Nat().SubOne(q) -+ -+ // lcm(a, b) = a×b / gcd(a, b) = a × (b / gcd(a, b)) -+ -+ // Our GCD requires at least one of the numbers to be odd. For LCM we only -+ // need to preserve the larger prime power of each prime factor, so we can -+ // right-shift the number with the fewest trailing zeros until it's odd. -+ // For odd a, b and m >= n, lcm(a×2ᵐ, b×2ⁿ) = lcm(a×2ᵐ, b). -+ az, bz := a.TrailingZeroBitsVarTime(), b.TrailingZeroBitsVarTime() -+ if az < bz { -+ a = a.ShiftRightVarTime(az) -+ } else { -+ b = b.ShiftRightVarTime(bz) -+ } -+ -+ gcd, err := bigmod.NewNat().GCDVarTime(a, b) -+ if err != nil { -+ return nil, err -+ } -+ if gcd.IsOdd() == 0 { -+ return nil, errors.New("rsa: internal error: gcd(a, b) is even") -+ } -+ -+ // To avoid implementing multiple-precision division, we just try again if -+ // the divisor doesn't fit in a single word. This would have a chance of -+ // 2⁻⁶⁴ on 64-bit platforms, and 2⁻³² on 32-bit platforms, but testing 2⁻⁶⁴ -+ // edge cases is impractical, and we'd rather not behave differently on -+ // different platforms, so we reject divisors above 2³²-1. -+ if gcd.BitLenVarTime() > 32 { -+ return nil, errDivisorTooLarge -+ } -+ if gcd.IsZero() == 1 || gcd.Bits()[0] == 0 { -+ return nil, errors.New("rsa: internal error: gcd(a, b) is zero") -+ } -+ if rem := b.DivShortVarTime(gcd.Bits()[0]); rem != 0 { -+ return nil, errors.New("rsa: internal error: b is not divisible by gcd(a, b)") -+ } -+ -+ return bigmod.NewModulusProduct(a.Bytes(p), b.Bytes(q)) -+} -+ - // randomPrime returns a random prime number of the given bit size following - // the process in FIPS 186-5, Appendix A.1.3. - func randomPrime(rand io.Reader, bits int) ([]byte, error) { -- if bits < 64 { -- return nil, errors.New("rsa: prime size must be at least 32-bit") -+ if bits < 16 { -+ return nil, errors.New("rsa: prime size must be at least 16 bits") - } - - b := make([]byte, (bits+7)/8) -diff --git a/src/crypto/internal/fips140/rsa/keygen_test.go b/src/crypto/internal/fips140/rsa/keygen_test.go -index 7d613e6ddf..9104a9dfd8 100644 ---- a/src/crypto/internal/fips140/rsa/keygen_test.go -+++ b/src/crypto/internal/fips140/rsa/keygen_test.go -@@ -6,8 +6,10 @@ package rsa - - import ( - "bufio" -+ "crypto/internal/fips140/bigmod" - "encoding/hex" - "fmt" -+ "math/big" - "os" - "strings" - "testing" -@@ -83,8 +85,94 @@ func TestMillerRabin(t *testing.T) { - } - } - -+func TestTotient(t *testing.T) { -+ f, err := os.Open("testdata/gcd_lcm_tests.txt") -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ var GCD, A, B, LCM string -+ var lineNum int -+ scanner := bufio.NewScanner(f) -+ for scanner.Scan() { -+ lineNum++ -+ line := scanner.Text() -+ if len(line) == 0 || line[0] == '#' { -+ continue -+ } -+ -+ k, v, _ := strings.Cut(line, " = ") -+ switch k { -+ case "GCD": -+ GCD = v -+ case "A": -+ A = v -+ case "B": -+ B = v -+ case "LCM": -+ LCM = v -+ -+ t.Run(fmt.Sprintf("line %d", lineNum), func(t *testing.T) { -+ if A == "0" || B == "0" { -+ t.Skip("skipping test with zero input") -+ } -+ if LCM == "1" { -+ t.Skip("skipping test with LCM=1") -+ } -+ -+ p, _ := bigmod.NewModulus(addOne(decodeHex(t, A))) -+ a, _ := bigmod.NewNat().SetBytes(decodeHex(t, A), p) -+ q, _ := bigmod.NewModulus(addOne(decodeHex(t, B))) -+ b, _ := bigmod.NewNat().SetBytes(decodeHex(t, B), q) -+ -+ gcd, err := bigmod.NewNat().GCDVarTime(a, b) -+ // GCD doesn't work if a and b are both even, but LCM handles it. -+ if err == nil { -+ if got := strings.TrimLeft(hex.EncodeToString(gcd.Bytes(p)), "0"); got != GCD { -+ t.Fatalf("unexpected GCD: got %s, want %s", got, GCD) -+ } -+ } -+ -+ lcm, err := totient(p, q) -+ if oddDivisorLargerThan32Bits(decodeHex(t, GCD)) { -+ if err != errDivisorTooLarge { -+ t.Fatalf("expected divisor too large error, got %v", err) -+ } -+ t.Skip("GCD too large") -+ } -+ if err != nil { -+ t.Fatalf("failed to calculate totient: %v", err) -+ } -+ if got := strings.TrimLeft(hex.EncodeToString(lcm.Nat().Bytes(lcm)), "0"); got != LCM { -+ t.Fatalf("unexpected LCM: got %s, want %s", got, LCM) -+ } -+ }) -+ default: -+ t.Fatalf("unknown key %q on line %d", k, lineNum) -+ } -+ } -+ if err := scanner.Err(); err != nil { -+ t.Fatal(err) -+ } -+} -+ -+func oddDivisorLargerThan32Bits(b []byte) bool { -+ x := new(big.Int).SetBytes(b) -+ x.Rsh(x, x.TrailingZeroBits()) -+ return x.BitLen() > 32 -+} -+ -+func addOne(b []byte) []byte { -+ x := new(big.Int).SetBytes(b) -+ x.Add(x, big.NewInt(1)) -+ return x.Bytes() -+} -+ - func decodeHex(t *testing.T, s string) []byte { - t.Helper() -+ if len(s)%2 != 0 { -+ s = "0" + s -+ } - b, err := hex.DecodeString(s) - if err != nil { - t.Fatalf("failed to decode hex %q: %v", s, err) -diff --git a/src/crypto/internal/fips140/rsa/rsa.go b/src/crypto/internal/fips140/rsa/rsa.go -index 7f759cff64..0bbf701050 100644 ---- a/src/crypto/internal/fips140/rsa/rsa.go -+++ b/src/crypto/internal/fips140/rsa/rsa.go -@@ -229,7 +229,7 @@ func checkPrivateKey(priv *PrivateKey) error { - // Check that de ≡ 1 mod p-1, and de ≡ 1 mod q-1. - // - // This implies that e is coprime to each p-1 as e has a multiplicative -- // inverse. Therefore e is coprime to lcm(p-1,q-1,r-1,...) = exponent(ℤ/nℤ). -+ // inverse. Therefore e is coprime to lcm(p-1,q-1) = λ(N). - // It also implies that a^de ≡ a mod p as a^(p-1) ≡ 1 mod p. Thus a^de ≡ a - // mod n for all a coprime to n, as required. - // -diff --git a/src/crypto/internal/fips140/rsa/testdata/gcd_lcm_tests.txt b/src/crypto/internal/fips140/rsa/testdata/gcd_lcm_tests.txt -new file mode 100644 -index 0000000000..b5a0c17ed2 ---- /dev/null -+++ b/src/crypto/internal/fips140/rsa/testdata/gcd_lcm_tests.txt -@@ -0,0 +1,279 @@ -+# GCD tests. -+# -+# These test vectors satisfy gcd(A, B) = GCD and lcm(A, B) = LCM. -+ -+GCD = 0 -+A = 0 -+B = 0 -+# Just to appease the syntax-checker. -+LCM = 0 -+ -+GCD = 1 -+A = 92ff140ac8a659b31dd904161f9213706a08a817ae845e522c3af0c9096699e059b47c8c2f16434b1c5766ebb384b79190f2b2a62c2378f45e116890e7bb407a -+B = 2f532c9e5902b0d68cd2ed69b2083bc226e8b04c549212c425a5287bb171c6a47fcb926c70cc0d34b8d6201c617aee66af865d31fdc8a2eeb986c19da8bb0897 -+LCM = 1b2c97003e520b0bdd59d8c35a180b4aa36bce14211590435b990ad8f4c034ce3c77899581cb4ee1a022874203459b6d53859ab1d99ff755efa253fc0e5d8487bb000c13c566e8937f0fe90b95b68bc278610d4f232770b08d1f31bee55a03da47f2d0ebb9e7861c4f16cc22168b68593e9efcde00f54104b4c3e1a0b294d7f6 -+ -+GCD = a -+A = faaffa431343074f5c5d6f5788500d7bc68b86eb37edf166f699b4d75b76dae2cb7c8f6eccae8f18f6d510ef72f0b9633d5740c0bebb934d3be796bd9a53808e -+B = 2f48ec5aa5511283c2935b15725d30f62244185573203b48c7eb135b2e6db5c115c9446ac78b020574665b06a75eb287e0dbeb5da7c193294699b4c2129d2ac4 -+LCM = 4a15f305e9622aa19bd8f39e968bfc16d527a47f7a5219d7b02c242c77ef8b608a4a6141f643ca97cedf07c0f1f3e8879d2568b056718aa15c0756899a08ccbe0a658bae67face96fa110edb91757bfa4828e8ff7c5d71b204f36238b12dd26f17be8ba9771f7068d63e41d423671f898f054b1187605754bc5546f2b02c5ac -+ -+GCD = 16 -+A = cf0b21bde98b41b479ac8071086687a6707e9efaacd4e5299668ce1be8b13290f27fd32ae68df87c292e8583a09d73ec8e8a04a65a487380dcd7dacca3b6e692 -+B = 3be3f563f81d5ad5c1211db7eff430aa345e830ce07b4bde7d4d32dba3ac618d2034351e5435fd6c7f077971fb4a1e83a7396a74fdff7fce1267112851db2582 -+LCM = 233a2188de2c017235024b182286f17562b2ee5ab9fdfe4efa2f61c4ff99fa44e1ead5bf6cde05bd7502ce78373c83e3f9dbab0c9bb8620a87c2640bce5d12c685af656df789bb3d0ba1edbaa98cf4f0166d422ab17aa6706f8132264d45b72827d6671a00a9186e723379e3a3bb7902d08865f357c74100059f83800241976 -+ -+GCD = 1 -+A = dd7b7597d7c1eb399b1cea9b3042c14bd6022d31b1d2642a8f82fc32de6eadaf012fbbf349eaec4922a8468740ca73c6090833d6a69a380ed947b39c2f9b0b76 -+B = 8e0dc8654e70eec55496038a8d3fff3c2086bc6dbfc0e2dbdf5bd7de03c5aef01a3982556ac3fc34fd5f13368be6cdc252c82367b7462e210f940f847d382dd9 -+LCM = 7ae667df4bd4dd35bbec28719a9f1b5e1f396a9ab386c086742a6ab3014a3386d39f35b50624d0c5b4e6b206c2635c7de5ea69e2faa85dd616a7e36622962a07632839857aa49332942feccff2aee1c962e2f4e8ccfd738a5da5bf528b4c5a2440409350f5a17a39d234403e8482ccf838e0d2758ccfb8018198a51dbb407506 -+ -+GCD = 1 -+A = 0 -+B = 1 -+LCM = 0 -+ -+GCD = 1 -+A = 1 -+B = 0 -+LCM = 0 -+ -+GCD = 1 -+A = 1 -+B = 1 -+LCM = 1 -+ -+GCD = 2b2 -+A = dfccaa3549c1b59ab3e114fe87dc5d187719abad58c51724e972741eb895ab79a49f385f61d531ec5c88dbb505ae375093fa848165f71a5ed65e7832a42ade191a -+B = fa58a81f43088da45e659fc1117d0f1cd015aa096c8e5377cf1832191baf7cc28b5c24998b93b64f8900a0973faedb9babaaf1854345f011739da8f1175d9684c -+LCM = 5132f7ab7a982b9dc55114bd96800b7637f9742cf8a7a00a0d69d5e4574fc85792c89a1c52bcfc74b9d7f3f6164819466c46b2d622e280ced7ad1211604084a15dc1fd1951a05c8ce37122c0ec15891d818a70d3763670ea3195098de9b1ca50ea89893a9753fb9ea801541058f44801f7f50967124abfc864a2b01c41f94193c -+ -+GCD = 8e -+A = 248d96a8a4cab0a1b194e08c1146868b094597cadbc35531f0ed2d77cba9f15cb5cc7c10e64ce054bf93396d25259d750b3de3aba65073db1fd2b852a6454ac1a -+B = 4c7bad8e1844901fd6a2ce2edc82e698d28ec95d6672ca148d85b49ecc78dd0a8b870e202244210bc98592b99ff6abbd20630f9eee7d46b15ccfae8d08b86799de -+LCM = 13b01f9d9c6c13e90c97e3d95bbce5a835c631b3de3bd4ff5df13ad850f5223dbdf71c53912275d0397df9335ef3a3ba8e4684c6b25962bb7b18bc74144cb5edf0196f79863a7ff032619a71646a92281f7baace7f223d254cb4d05ec19bf8d4c8ce4455a9d770daec89c0d3cf338cbdae39cf982b3c4568f5c9def4e1133d28a -+ -+GCD = 3e55 -+A = 2fa97382f46676b7a4cc2b8153f17b58792d24660e187d33ce55c81cc193ccb6e1e2b89feea1d5fd8faa36e13bf947fb48635e450a4d1488d0978324194a1f43c6 -+B = ab08ad074139963bc18e5d87ba68db64ca6f4c279616c64039b02c55f2375b3bc04114e8e05e1ba92fb6470768f61d123845aea36774c18612736a220934561faf -+LCM = 82c7c377ecda2cb9228604cd287df5eff94edd4a539c3eb3b3fdd4b4a79d2f4eaf2b22f8286272d3dad2e370cfcd9ea4d93ebb3f049c52b8fa23b68a5bf79af989822e2cfb978f68c6a5058f47319dffcb455b089b06ae6db9e5c8a2b6e951d6e118bd2b4cd08b6e5733476a446a57387d940d1289ec00e24315821ed3a5daf2 -+ -+GCD = a7a -+A = 923706dfed67834a1e7e6c8e8e9f93bfbc0b43ca1f324886cf1f1380fb9b77109275d4b50af1b7689802fe9b3623ac46c7ba0e17e908c20278127b07a5c12d86ec -+B = 64473e878a29021fac1c1ce34a63eae1f4f83ee6851333b67213278b9a4a16f005cba0e8cdb410035bb580062f0e486c1a3a01f4a4edf782495f1dc3ebfa837d86 -+LCM = 57785ca45b8873032f1709331436995525eed815c55140582ce57fd852116835deac7ca9d95ce9f280e246ea4d4f1b7140ab7e0dd6dc869de87f1b27372098b155ad0a1828fd387dff514acc92eae708609285edaab900583a786caf95153f71e6e6092c8c5ee727346567e6f58d60a5e01c2fa8ebcf86da9ea46876ecc58e914 -+ -+GCD = 42 -+A = 0 -+B = 42 -+LCM = 0 -+ -+GCD = 42 -+A = 42 -+B = 0 -+LCM = 0 -+ -+GCD = 42 -+A = 42 -+B = 42 -+LCM = 42 -+ -+GCD = f60d -+A = ef7886c3391407529d5cf2e75ed53e5c3f74439ad2e2dc48a79bc1a5322789b4ced2914b97f8ff4b9910d212243b54001eb8b375365b9a87bd022dd3772c78a9fd63 -+B = d1d3ec32fa3103911830d4ec9f629c5f75af7039e307e05bc2977d01446cd2cbeeb8a8435b2170cf4d9197d83948c7b8999d901fe47d3ce7e4d30dc1b2de8af0c6e4 -+LCM = cc376ed2dc362c38a45a719b2ed48201dab3e5506e3f1314e57af229dc7f3a6a0dad3d21cfb148c23a0bbb0092d667051aa0b35cff5b5cc61a7c52dec4ed72f6783edf181b3bf0500b79f87bb95abc66e4055f259791e4e5eb897d82de0e128ecf8a091119475351d65b7f320272db190898a02d33f45f03e27c36cb1c45208037dc -+ -+GCD = 9370 -+A = 1ee02fb1c02100d1937f9749f628c65384ff822e638fdb0f42e27b10ee36e380564d6e861fcad0518f4da0f8636c1b9f5124c0bc2beb3ca891004a14cd7b118ddfe0 -+B = 67432fd1482d19c4a1c2a4997eab5dbf9c5421977d1de60b739af94c41a5ad384cd339ebfaa43e5ad6441d5b9aaed5a9f7485025f4b4d5014e1e406d5bd838a44e50 -+LCM = 159ff177bdb0ffbd09e2aa7d86de266c5de910c12a48cbe61f6fa446f63a2151194777555cd59903d24cb30965973571fb1f89c26f2b760526f73ded7ee8a34ebcecd1a3374a7559bcdb9ac6e78be17a62b830d6bb3982afdf10cf83d61fd0d588eab17d6abef8e6a7a5763fcb766d9a4d86adf5bb904f2dd6b528b9faec603987a0 -+ -+GCD = c5f -+A = 5a3a2088b5c759420ed0fb9c4c7685da3725b659c132a710ef01e79435e63d009d2931ea0a9ed9432f3d6b8851730c323efb9db686486614332c6e6ba54d597cf98 -+B = 1b1eb33b006a98178bb35bbcf09c5bebd92d9ace79fa34c1567efa8d6cf6361547807cd3f8e7b8cd3ddb6209dccbae4b4c16c8c1ec19741a3a57f61571882b7aed7 -+LCM = c5cbbbe9532d30d2a7dd7c1c8a6e69fd4fa4828a844d6afb44f3747fef584f7f1f3b835b006f8747d84f7699e88f6267b634e7aef78d6c7584829537d79514eec7d11219721f91015f5cefdc296261d85dba388729438991a8027de4827cd9eb575622e2912b28c9ce26d441e97880d18db025812cef5de01adeaec1322a9c9858 -+ -+GCD = e052 -+A = 67429f79b2ec3847cfc7e662880ab1d94acdf04284260fcfffd67c2862d59704ed45bcc53700c88a5eea023bc09029e9fd114fc94c227fd47a1faa1a5ef117b09bd2 -+B = 39faa7cbdeb78f9028c1d50ab34fbe6924c83a1262596f6b85865d4e19cc258b3c3af1ee2898e39e5bee5839e92eac6753bbbb0253bd576d1839a59748b778846a86 -+LCM = 1ab071fb733ef142e94def10b26d69982128561669e58b20b80d39cf7c2759d26b4a65d73b7f940c6e8fc417180ef62d7e52ac24678137bd927cd8d004ad52b02affe176a1ecde903dbc26dcc705678f76dd8cd874c0c3fe737474309767507bbe70dd7fb671bbb3694cedf0dcdaa0c716250ddd6dfec525261572fa3e1387f7b906 -+ -+GCD = 3523 -+A = 0 -+B = 3523 -+LCM = 0 -+ -+GCD = 3523 -+A = 3523 -+B = 0 -+LCM = 0 -+ -+GCD = 3523 -+A = 3523 -+B = 3523 -+LCM = 3523 -+ -+GCD = f035a941 -+A = 16cd5745464dfc426726359312398f3c4486ed8aaeea6386a67598b10f744f336c89cdafcb18e643d55c3a62f4ab2c658a0d19ea3967ea1af3aee22e11f12c6df6e886f7 -+B = 74df09f309541d26b4b39e0c01152b8ad05ad2dfe9dd2b6706240e9d9f0c530bfb9e4b1cad3d4a94342aab309e66dd42d9df01b47a45173b507e41826f24eb1e8bcc4459 -+LCM = b181771d0e9d6b36fdfcbf01d349c7de6b7e305e1485ea2aa32938aa919a3eee9811e1c3c649068a7572f5d251b424308da31400d81ac4078463f9f71d7efd2e681f92b13a6ab3ca5c9063032dcbdf3d3a9940ce65e54786463bbc06544e1280f25bc7579d264f6f1590cf09d1badbf542ce435a14ab04d25d88ddbac7d22e8cae1c91f -+ -+GCD = 33ad1b8f -+A = 1af010429a74e1b612c2fc4d7127436f2a5dafda99015ad15385783bd3af8d81798a57d85038bcf09a2a9e99df713b4d6fc1e3926910fbbf1f006133cb27dc5ebb9cca85 -+B = 92a4f45a90965a4ef454f1cdd883d20f0f3be34d43588b5914677c39d577a052d1b25a522be1a656860a540970f99cbc8a3adf3e2139770f664b4b7b9379e13daf7d26c -+LCM = 4c715520ed920718c3b2f62821bc75e3ff9fd184f76c60faf2906ef68d28cd540d3d6c071fa8704edd519709c3b09dfaee12cb02ab01ad0f3af4f5923d5705ce6d18bcab705a97e21896bb5dd8acb36ee8ec98c254a4ddc744297827a33c241f09016a5f109248c83dd41e4cea73ce3eabb28d76678b7e15545b96d22da83c111b6b624 -+ -+GCD = dc0429aa -+A = ccb423cfb78d7150201a97114b6644e8e0bbbb33cadb0ef5da5d3c521a244ec96e6d1538c64c10c85b2089bdd702d74c505adce9235aa4195068c9077217c0d431de7f96 -+B = 710786f3d9022fc3acbf47ac901f62debcfda684a39234644bac630ab2d211111df71c0844b02c969fc5b4c5a15b785c96efd1e403514235dc9356f7faf75a0888de5e5a -+LCM = 6929af911850c55450e2f2c4c9a72adf284fe271cf26e41c66e1a2ee19e30d928ae824f13d4e2a6d7bb12d10411573e04011725d3b6089c28d87738749107d990162b485805f5eedc8f788345bcbb5963641f73c303b2d92f80529902d3c2d7899623958499c8a9133aae49a616c96a2c5482a37947f23af18c3247203ac2d0e760340e6 -+ -+GCD = 743166058 -+A = 16cd476e8031d4624716238a3f85badd97f274cdfd9d53e0bd74de2a6c46d1827cc83057f3889588b6b7ca0640e7d743ed4a6eaf6f9b8df130011ecc72f56ef0af79680 -+B = 86eba1fc8d761f22e0f596a03fcb6fe53ad15a03f5b4e37999f60b20966f78ba3280f02d3853f9ace40438ccfaf8faed7ace2f2bf089b2cdd4713f3f293bf602666c39f8 -+LCM = 1a7a1b38727324d6ba0290f259b8e2b89c339b2445cada38a5a00ded1468ab069f40678ce76f7f78c7c6f97783cc8a49ef7e2a0c73abbac3abc66d1ce99566ce7f874a8949ca3442051e71967695dc65361184748c1908e1b587dc02ed899a524b34eb30b6f8db302432cfa1a8fbf2c46591e0ab3db7fd32c01b1f86c39832ee9f0c80 -+ -+GCD = 6612ba2c -+A = 0 -+B = 6612ba2c -+LCM = 0 -+ -+GCD = 6612ba2c -+A = 6612ba2c -+B = 0 -+LCM = 0 -+ -+GCD = 6612ba2c -+A = 6612ba2c -+B = 6612ba2c -+LCM = 6612ba2c -+ -+GCD = 2272525aa08ccb20 -+A = 11b9e23001e7446f6483fc9977140d91c3d82568dabb1f043a5620544fc3dda233b51009274cdb004fdff3f5c4267d34181d543d913553b6bdb11ce2a9392365fec8f9a3797e1200 -+B = 11295529342bfb795f0611d03afb873c70bd16322b2cf9483f357f723b5b19f796a6206cf3ae3982daaeafcd9a68f0ce3355a7eba3fe4e743683709a2dd4b2ff46158bd99ff4d5a0 -+LCM = 8d4cbf00d02f6adbaa70484bcd42ea932000843dcb667c69b75142426255f79b6c3b6bf22572597100c06c3277e40bf60c14c1f4a6822d86167812038cf1eefec2b0b19981ad99ad3125ff4a455a4a8344cbc609e1b3a173533db432bd717c72be25e05ed488d3970e7ed17a46353c5e0d91c8428d2fec7a93210759589df042cab028f545e3a00 -+ -+GCD = 3480bf145713d56f9 -+A = 8cf8ef1d4f216c6bcec673208fd93b7561b0eb8303af57113edc5c6ff4e1eeae9ddc3112b943d947653ba2179b7f63505465126d88ad0a0a15b682f5c89aa4a2a51c768cd9fdeaa9 -+B = a6fd114023e7d79017c552a9051ca827f3ffa9f31e2ee9d78f8408967064fcdc9466e95cc8fac9a4fa88248987caf7cf57af58400d27abd60d9b79d2fe03fad76b879eceb504d7f -+LCM = 1c05eee73a4f0db210a9007f94a5af88c1cdd2cba456061fd41de1e746d836fa4e0e972812842e0f44f10a61505f5d55760c48ba0d06af78bb6bde7da8b0080b29f82b1161e9c0b5458e05ac090b00f4d78b1cc10cf065124ba610e3acab092a36fe408525e21c0ddc7c9696ed4e48bd2f70423deecfe62cecc865c6088f265da0e5961d3f3a84f -+ -+GCD = 917e74ae941fcaae -+A = 652f8a92d96cbf0a309629011d0fbaceb1266bc2e8243d9e494eead4cf7100c661b537a8bea93dec88cfc68597d88a976c125c3b4de19aba38d4ea9578202e59848d42652518348a -+B = 32e07b71979d57e8344e97c39680a61e07d692d824ae26b682156890792d8a766ee29a4968f461aaced5bf049044fba2f4120b1c1f05985676f975d4582e9e82750d73c532cd07b2 -+LCM = 23620c7b897dc26c7717e32f3517ac70bf09fbe08f7255ab010cf4cf946f4e96304c425043452c5d5a0e841d3a3cfd9c2d84d9256f3b5974fe3ebfa9255fe20a710d3e6511606c0d85970381101c7f4986d65ad6a73a71507f146b11f903043cfa805cc0b14d4f3072da98bf22282f7762040406c02d5b3ef9e7587f63bab8b29c61d8e30911aa96 -+ -+GCD = 2b9adc82005b2697 -+A = 19764a84f46045ef1bca571d3cbf49b4545998e64d2e564cc343a53bc7a0bcfbe0baa5383f2b346e224eb9ce1137d9a4f79e8e19f946a493ff08c9b423574d56cbe053155177c37 -+B = 1bbd489ad2ab825885cdac571a95ab4924e7446ce06c0f77cf29666a1e20ed5d9bc65e4102e11131d824acad1592075e13024e11f12f8210d86ab52aa60deb250b3930aabd960e5a -+LCM = 1032a0c5fffc0425e6478185db0e5985c645dd929c7ebfeb5c1ee12ee3d7b842cfab8c9aa7ff3131ac41d4988fb928c0073103cea6bb2cc39808f1b0ad79a6d080eac5a0fc6e3853d43f903729549e03dba0a4405500e0096b9c8e00510c1852982baec441ed94efb80a78ed28ed526d055ad34751b831b8749b7c19728bf229357cc5e17eb8e1a -+ -+GCD = 8d9d4f30773c4edf -+A = 0 -+B = 8d9d4f30773c4edf -+LCM = 0 -+ -+GCD = 8d9d4f30773c4edf -+A = 8d9d4f30773c4edf -+B = 0 -+LCM = 0 -+ -+GCD = 8d9d4f30773c4edf -+A = 8d9d4f30773c4edf -+B = 8d9d4f30773c4edf -+LCM = 8d9d4f30773c4edf -+ -+GCD = 6ebd8eafb9a957a6c3d3d5016be604f9624b0debf04d19cdabccf3612bbd59e00 -+A = 34dc66a0ffd5b8b5e0ffc858dfc4655753e59247c4f82a4d2543b1f7bb7be0e24d2bbf27bb0b2b7e56ee22b29bbde7baf0d7bfb96331e27ba029de9ffdff7bdb7dc4da836d0e58a0829367ec84ea256833fd4fe1456ad4dd920557a345e12000 -+B = 1f3406a20e20ebf96ccb765f898889a19b7636608fd7dc7c212607b641399543f71111d60e42989de01eaa6ff19a86ea8fbde1a3d368c0d86dc899e8e250fc764090f337958ca493119cbb4ad70cbfae7097d06d4f90ec62fbdd3f0a4496e600 -+LCM = ee502c50e3667946e9089d0a9a0382e7fd0b75a17db23b56a0eec997a112c4dbd56d188808f76fe90451e5605550c9559ef14a95014c6eb97e9c1c659b98515c41470142843de60f72fb4c235faa55b0a97d943221003d44e2c28928f0b84bf071256254897ed31a7fd8d174fc962bc1311f67900ac3abcad83a28e259812f1ee229511ab1d82d41f5add34693ba7519babd52eb4ec9de31581f5f2e40a000 -+ -+GCD = ef7399b217fc6a62b90461e58a44b22e5280d480b148ec4e3b4d106583f8e428 -+A = 7025e2fe5f00aec73d90f5ad80d99ca873f71997d58e59937423a5e6ddeb5e1925ed2fd2c36a5a9fc560c9023d6332c5d8a4b333d3315ed419d60b2f98ccf28bbf5bf539284fd070d2690aeaac747a3d6384ee6450903a64c3017de33c969c98 -+B = df0ac41dbabce1deeb0bceb1b65b1079850052ecf6534d0cff84a5a7fb5e63baee028d240f4419925154b96eaa69e8fbb1aae5102db7916234f290aa60c5d7e69406f02aeea9fe9384afbff7d878c9ac87cd31f7c35dff243b1441e09baff478 -+LCM = 687669343f5208a6b2bb2e2efcac41ec467a438fde288cc5ef7157d130139ba65db9eb53e86a30c870bd769c0e0ab15a50f656cd9626621ae68d85eaff491b98da3ea5812062e4145af11ea5e1da457084911961ef2cd2ac45715f885ba94b4082aa76ffd1f32461f47c845b229d350bf36514c5ce3a7c782418746be342eca2721346ade73a59475f178c4f2448e1326110f5d26a0fef1a7a0c9288489e4dc8 -+ -+GCD = 84b917557acf24dff70cb282a07fc52548b6fbbe96ca8c46d0397c8e44d30573 -+A = 81dbb771713342b33912b03f08649fb2506874b96125a1ac712bc94bfd09b679db7327a824f0a5837046f58af3a8365c89e06ff4d48784f60086a99816e0065a5f6f0f49066b0ff4c972a6b837b63373ca4bb04dcc21e5effb6dfe38271cb0fa -+B = 1da91553c0a2217442f1c502a437bb14d8c385aa595db47b23a97b53927b4493dd19f1bc8baf145bc10052394243089a7b88d19b6f106e64a5ab34acad94538ab504d1c8ebf22ac42048bbd1d4b0294a2e12c09fe2a3bd92756ba7578cb34b39 -+LCM = 1d0530f8142754d1ee0249b0c3968d0ae7570e37dadbe4824ab966d655abf04cd6de5eb700eba89d8352dec3ae51f2a10267c32fbd39b788c7c5047fe69da3d7ad505435a6212f44899ba7e983bb780f62bcdee6f94b7dba8af7070a4cc008f351ae8be4579bc4a2e5c659ce000ad9c8cdc83723b32c96aeb0f5f4127f6347353d05525f559a8543cd389ad0af6f9d08a75b8c0b32419c097e6efe8746aee92e -+ -+GCD = 66091477ea3b37f115038095814605896e845b20259a772f09405a8818f644aa -+A = cedac27069a68edfd49bd5a859173c8e318ba8be65673d9d2ba13c717568754ed9cbc10bb6c32da3b7238cff8c1352d6325668fd21b4e82620c2e75ee0c4b1aff6fb1e9b948bbdb1af83cecdf356299b50543b72f801b6a58444b176e4369e0 -+B = 5f64ca1ba481f42c4c9cf1ffa0e515b52aa9d69ceb97c4a2897f2e9fa87f72bae56ee6c5227f354304994c6a5cc742d9f09b2c058521975f69ca5835bce898cf22b28457cd7e28870df14e663bb46c9be8f6662f4ff34d5c4ae17a888eba504e -+LCM = c163cb28642e19a40aa77887c63180c2c49fc10cda98f6f929c8131752ea30b5283a814a81681b69b9d1762e6c1a9db85f480bc17f998d235fd7e64c1caa70ef170c9e816d3e80f516b29f2c80cfb68bf208b4d5082ef078da4314b3f20c7d6c54b0aeb378096b029a7b61c0a4cd14aeddc01004c53915a4f692d2291752e5af46b23d7fa6dd61f2d56c6f4bf8e6119688abac8fd7aba80e846a7764bb3fca0 -+ -+GCD = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 -+A = 0 -+B = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 -+LCM = 0 -+ -+GCD = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 -+A = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 -+B = 0 -+LCM = 0 -+ -+GCD = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 -+A = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 -+B = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 -+LCM = bb80bf51757ba696c700fa4e4c0132b3151d2bf9ebff8382f808ded78be67182 -+ -+GCD = 120451d8307219aa0c96f328ad653ccd462e92423ca93ed8a3dde45bf5cb9b13cdaf9800e4d05dd71c4db6a129fb3280ee4ec96ec5297d881c1a8b5efccbd91fef21f5c5bf5fba42a4c8eaa358f620a074b7a17054527bdaa58d5acaa0dfdc48ecba1a10ebf4d57bb4215de406e6be13fed3fe493b1cd1e2d11a8d4ac03c47756 -+A = 3f8179a8e1f0b342475a855c3e1bae402dd41424cf24a0b4d2e263c8efb08bde7d92eae8607fb5e88b1378f0f1bd0733f229a35be6b1383a48d32749d5d6b32427d26323b7ab05bb5781289e96bfbc21971439319b15f6c0fe93fdb35d0b67ec41443c59a081dd3cef047ac797fccb45bece84c0bb0bb7e1797259526d8ec9cc63ba4d32cfc692ccd3d243cb2b53ac216312f3a8e8c0daa09d21b6150d697639a5e52059414a417c607be8ec0eee2e708219cadbaf37a369c4485b01ed87bbc2 -+B = 2c474e396a2dd9cd10b9d7313f69d3b4ca123e9fd853edd488339236d14c56453a1381958864a04d2624e81995dabcdd0ccf60db9917813f887de68da075d0ea4440001e18f470e43b38ee3440b49be651d709fbdef980e3e4149913f4ae2681124f54523f4881376ddb533b5219e804cc26f4c2e577be4e02613c4da80ba1215775b0a5178a965ad47bd2befb32493943ded1004ef66347b4983f8d1ba990d4a943505dfce6debcfb322842ed88106cd6dee9aa592ff0d2274bc727a6e1f14c -+LCM = 9c129cf649555bfd2d3d9c64dc6d6f022295e53bca5d2f218adaa66aa60eb4694429b7e83bf81b6df4459c5104023ab9a33f006ffcd8114507baa17e2ef6fe23ebdd4740f66879033da2041f2cb7ba517ad3526ffe75614ea9432c085f71b2d65a736bac7ba42b639e330b82733372083843dcb78b6a273ab20e0d4b7c8998a14048aa15bb20a0a0bd997917107274c89b4cec175fb98043d52e6c555bd9e0036566d052a6d4e7e276d1e8835e1f06e3ca46d47747ba586e95fb1a790d992834b7c3e136141eb8a434e6c12067246ac3c0a81c69e03b1ed28aa0b3173d6eff83d278c2f461a47a416f3f9a5dae3bb410fd18817bd4115e7f1e84b936cc02364 -+ -+GCD = 95aa569a2c76854300d7660847dd20fe0b8c445fdbcaa98465cee61aee76ad6a438e75a8c573198570ffb62bc07ec3a2be0ae0a1f631670fa88d6f75f3161e8b9a4d44b6801ffc884c7f469c5ed1f27b1edecce9f2977f9e92d1a3b230492fea7e6f2af739dc158a7fbd29856cbedb57b4119e64b27ab09eb1c2df01507d6e7fd -+A = 4c653b5bfec44e9be100c064dffe5d8cd59b0cf4cc56b03eabb4ef87cfda6506c9a756b811907fe9d8b783eb7a0b9e129773bf1da365ddb488d27b16fb983e89345d1ccdb4f06a67a11925c3f266373be5d7b0075189c6f3c2157e2da197058fe0a7bcc50adc34e99e254a29abbe2d5948d3157e1b0c3fca3d641760f7b9862843b63abef0b3d83fd486f4526b30382fda355575da30e9a106718a3921774c4d69f5311f8d737fe618f5236b4763fe1b2ee7f13184db67367d3903c535ff6d7b -+B = 2dcca83c99a28e9fd2f84e78973699baf2f04fd454094730948b22477834a0064817b86e0835e6d7b26e5b0b1dcf4ad91a07ac0780d6522df1fcac758cf5db6c2a5623d7c0f1afefd5718f7b6de639867d07a9ec525991304e9355d1635104bea837f74758d6aa2aab4e4afbb606af1d98de7417505e4710cd0589bdff9a0bf38a857cc59a5f1781043e694fc2337fd84bdeb28b13a222bb09328a81ec409ad586e74236393d27398cc24d412135e34247c589149e134b97f4bd538ac9a3424b -+LCM = 1760c0b0066aa0695767099e87e9388729ea89b8e8c36bddcd04d257591e741613c07b0e69447c0a468c33a745084171e06523d987d8db40a1433bf435325e8a724a0876503b34495170ff3671d42117a2e4f3a75b1d9dd809a34fa0fb26fe50d84f80a9b02e40190e5efb927a5a61a03f13edbce2e666af6c3a2a9bcb84e47e3090008753ff27c4b8cf06480f471379a93f5230923623a83b286b71a555cd5e5347282f664ed90b14b2c4de84a70375e488211a7b3931119ef3bbe029b712389fe784818a0bf29d80733ce9cc940c547aa1eb3f06d492eb676bf37802283c82ce76156dfaab5c2d5107e08062681b5fa169f6eb68e1ab8bd9b2005e90bd4fd -+ -+GCD = 244b9b1290cf5b4ba2f810574c050651489f2d3a2b03e702b76ebfaf4e33de9bbe5da24c919e68d3a72eadd35982b3a89c6b18b38ff7082ac65263e52b6ec75a5717b971c98257b194c828bff0216a99536603b41a396ea2fb50f5ea7cf3edf10bb0d039123e78593ae9ffcbbba02e51e038533e83b6bc73c70551d6467f39809 -+A = 41a0b1310669500681cdf888836f6c556758750f562d743ac780dd4c0d161856380e44fdbb1f8a2786bf45be6b0e7f1cb2cd85f6b9e50acc72793d92383c7d7fb796fc74d32e8fac8225bdc19ae47546d9c9c75f5f06ca684f07daccaf89ccf2cddeb7ec255d530c7dd1e71daf44cafdc9d30fbcb1cbaefae3480585f79f4177e3834a5bc91845e2e8cd8aeb27f484e5e5b2c3c076dbb6c23e91303f0a0fdde83cd33a8ea6ed1549e727b4d766c1017c169710fd98e1585d60f66e121f9180b3 -+B = 251f5aeaa60b3959285f49540cdaf8e21451110bbddb9933bbbcaea3112f4eb45e435a3ba37c52d2ab79ce997a8f6c829b3aa561f2852924b8effb52396d09d2bf257ebb4fb56c7aa25648f69b06d2cd01e876c9f9c0679de9e6fffa79eb7e603723e5af7de46ee405a5a079229577b5b6fffb8d43e391fe6f4eb89638e64d6eff8026249aaa355a91625eb0bfd14caa81e4c3586aaa2e94fde143a44f223a91e226661d12f55dfcdb4215e5a64e14e968005733be6a71c465de312ca109b34a -+LCM = 431f918b274f3e43f446e4e85567883d6536a0332db662cef088f5a36b0f4b68372048174ba10fee94b9f8f1c2e189c974be2e6e8ae8e2ae108445326d40f63e38d8d4e2e46174589a3cbc9583e0036dc8146e79eee9e96f4436313b3f143dd0f5aceab05243def7f915169c360f55ef123977cf623c5ba432c3259c62fb5e37d5adab0f24b825aa4ada99ec4e83e9ca4698399e1ed633091ce5f9844c540a642cd264201116ed4168aa2105a5159f5df064f845830c469140f766c7319052ce59bd1ad7c3f2d8c30e54f147f6aeb5586c70c984302ba18d854a60aec01b394c7d66fa33fe18fe4a8cfb3238df219294e6e42190a30d28b10049a1b75853a4e -+ -+GCD = 206695d52bc391a4db61bf8cb6ea96188333a9c78f477ee76976c2346dad682cf56ca6f176d86ef67d41ff5921b6162b0eca52359975872430dd14c45643eacdf028d830770714c033fd150669705851b2f02de932322d271d565d26768530c3f6cb84f0b3356f970b9070b26c050ead0417152c324c8ffe266d4e8b5b7bef3a -+A = 1114eb9f1a9d5947eb1399e57f5c980833489685023ed2fe537fe1276c1e026b9a19e6fff55aa889d6c4e977b6e6f3111e2ad463138637b50f42cf32e57d83f282de9e72f813e5969195159a666d74dcd689bd527c60199ae327f7bd548ac36868fea5fdf6f35d19b921e7c10b6448ca480de6826478cd0642d72f05af3f8e65ce42409fbd49f56e81946e89c8e83962c4edc0ed54600600a305e52d081aed3c351e450e11f8fb0ce5754c92cf765b71393b2b7a89c95df79b9ea1b3cb600862 -+B = 1d8f3179ca7b5cc7119360c10de939ffa57c9043da2f2b0ca3009c9bdad9f19ed16e3c2c197bef4b527fa1bf2bbab98b77e26c329911db68bd63d3d0fbfc727a977395b9ad067106de3094d68e097830858c5ccfa505fc25e972bdee6f347e7d1163efacd3d29a791ec2a94ffeed467884ae04896efc5e7e5f43d8d76c147e3c9951a1999173bc4e5767d51268b92cc68487ba1295372143b538711e0a62bf0ac111cc750ca4dd6c318c9cbe106d7fc492261404b86a1ba728e2d25b1976dc42 -+LCM = f9570211f694141bfb096560551080cbe02a80271b4505591aaea9e3b99ea1d5ac1c1f2378fd72799e117ac2a73381b1ad26314e39972164d93971479ee3ba21a4d98cef0bd299d540ce5826995dcee0de420dff73d30b23cbf3188c625c7696df517535bc5675d71faa00807efbebdca547933f4a37849d1c014484a77da6df0670c4974bcc91eb5f5fe5faf9dd095ef195ec32ad9eeebf0e63288b4032ed9e70b888afc642f4ff96f0b4c0a68787301c12e4527fe79bdfe72dd3844ab5e094a9295df6616f24d1b9eeebc2116177dacf91969dda73667bc421ef3ccd8d5c23dddc283f5d36568d31f2654926be67f78e181075bdc148f2b39c630b141ae8a -+ -+GCD = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 -+A = 0 -+B = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 -+LCM = 0 -+ -+GCD = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 -+A = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 -+B = 0 -+LCM = 0 -+ -+GCD = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 -+A = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 -+B = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 -+LCM = 3d319c42d872f21131ce5ff3ab8bec94339308e620316dda218e85fedcd511cd62f0b2f3448d5e58fd3520ae8118abd54ead9ad9e8ec3890365c6b2cca2172d4b8839b2d2c5ab02f65180826cb0cd5c9798f5d6261efe6e6ec31dea047da7c486b0590359e6f333557f67ceebf9ea9cd5dd986a999a8c88bdbd0ca21816b2423 -+ -+GCD = 2 -+A = 14e95a85e59ade9ef39e2f400c65db18702fa5fc485b9bba479a5282b2206129160e54f73ef4917983c17b4c5ebff7be112a886de069706eee29ba902515cb038 -+B = ddcfff1d39c90c599f55495bf71c1e7597c6b08b7430707f360c6a6e5137bbc7b403c6d9e2c34f3d2f29d5d32b869346853c2de239cc35381bdfb4a01569211a -+LCM = 90f38564ee72e55d362c04599e7d74f068c75f541b84e97abba2841f1a9f66b06b5c9009f6a4c2e319fced85270588de03ccebddbd9279aaecb13bdc1dbea7f42acaee751cb7da83779b8785cc86f41b94b13b54964208ca287d981634778d1096f20e76ca636c0717fd27e0800c43f599a5eded807421b502eaf9990a8c8ed8 -+ -+GCD = 4 -+A = 3c719c1c363cdeb7b57c2aabb71f425da4c3e6d3e447204d555e7cf0f3d372bdda906f36078045044978dafc20171767c8b1464d52dfdf3e2ba8a4906da033a8 -+B = 30fe0ef151ac51404e128c064d836b191921769dc02d9b09889ed40eb68d15bfdd2edea33580a1a4d7dcee918fefd5c776cbe80ca6131aa080d3989b5e77e1b24 -+LCM = 2e4526157bbd765b0486d90bcd4728f890bc6dbd9a855c67ca5cb2d6b48f8e74e1d99485999e04b193afca58dbf282610185d6c0272007744ff26e00dbdc813929b47940b137dc56ba974da07d54a1c50ec4a5c2b26e83f47cf17f4ccce8c3687e8d1e91d7c491a599f3d057c73473723ce9eee52c20fe8ae1595447552a7ee8 -+ -+GCD = 10 -+A = 44e04071d09119ea9783a53df35de4a989200133bb20280fdca6003d3ca63fdd9350ad1a1673d444d2f7c7be639824681643ec4f77535c626bd3ee8fa100e0bb0 -+B = ca927a5a3124ce89accd6ac41a8441d352a5d42feb7f62687a5ebc0e181cc2679888ecc2d38516bdc3b3443550efccac81e53044ae9341ecace2598fe5ce67780 -+LCM = 36805ba9b2412a0cb3fe4ed9bdabfa55515c9d615a3d0af268c45c5f6098d2de4a583f3791f1e3883c55d51ce23c5658fd0e8faa9a3709a1cfbd6a61dbab861690f27c86664f084c86cfd4a183b24aaadf59a6f8cbec04f1b0ded8a59b188cb46ae920052e3e099a570540dbc00f7d4a571eef08aa70d2d189a1804bf04e94a80 -+ -+GCD = 100 -+A = 73725032b214a677687c811031555b0c51c1703f10d59b97a4d732b7feaec5726cb3882193419d3f057583b2bc02b297d76bb689977936febaae92638fdfc46a00 -+B = 979f4c10f4dc60ad15068cedd62ff0ab293aeaa1d6935763aed41fe3e445de2e366e8661eadf345201529310f4b805c5800b99f351fddab95d7f313e3bb429d900 -+LCM = 4460439b4be72f533e9c7232f7e99c48328b457969364c951868ceab56cb2cbbeda8be2e8e3cae45c0758048468b841fdb246b2086d19b59d17b389333166ab82ed785860620d53c44f7aaaff4625ee70fb8072df10fb4d1acb142eadc02978ff2bb07cea9f434e35424b3323a7bda3a1a57aa60c75e49ebb2f59fb653aa77da00 -+ -+GCD = 100000000 -+A = f8b4f19e09f5862d79fb2931c4d616a1b8e0dd44781ca52902c8035166c8fca52d33a56ff484c365ec1257de7fa8ed2786163cfc051d5223b4aad859a049e8ba00000000 -+B = 6e54cb41b454b080e68a2c3dd0fa79f516eb80239af2be8250ca9cd377ba501aabafc09146fad4402bdc7a49f2c3eec815e25f4c0a223f58e36709eefd92410500000000 -+LCM = 6b3020a880ddeff9d17d3dc234da8771962de3322cd15ba7b1e4b1dd4a6a2a802a16c49653865c6fdf6c207cbe0940f8d81ef4cb0e159385fd709d515ee99d109ad9ad680031cbae4eab2ed62944babdade4e3036426b18920022f737897c7d751dce98d626cdda761fec48ad87a377fb70f97a0a15aa3d10d865785719cc5a200000000 -diff --git a/src/crypto/internal/fips140test/check_test.go b/src/crypto/internal/fips140test/check_test.go -index b156de2cbb..6b0cd3f39e 100644 ---- a/src/crypto/internal/fips140test/check_test.go -+++ b/src/crypto/internal/fips140test/check_test.go -@@ -5,15 +5,14 @@ - package fipstest - - import ( -+ "crypto/internal/fips140" - . "crypto/internal/fips140/check" - "crypto/internal/fips140/check/checktest" - "fmt" - "internal/abi" -- "internal/asan" - "internal/godebug" - "internal/testenv" - "os" -- "runtime" - "testing" - "unicode" - "unsafe" -@@ -35,12 +34,8 @@ func TestFIPSCheckVerify(t *testing.T) { - return - } - -- if !Supported() { -- t.Skipf("skipping on %s-%s", runtime.GOOS, runtime.GOARCH) -- } -- if asan.Enabled { -- // Verification panics with asan; don't bother. -- t.Skipf("skipping with -asan") -+ if err := fips140.Supported(); err != nil { -+ t.Skipf("skipping: %v", err) - } - - cmd := testenv.Command(t, os.Args[0], "-test.v", "-test.run=TestFIPSCheck") -@@ -57,8 +52,8 @@ func TestFIPSCheckInfo(t *testing.T) { - return - } - -- if !Supported() { -- t.Skipf("skipping on %s-%s", runtime.GOOS, runtime.GOARCH) -+ if err := fips140.Supported(); err != nil { -+ t.Skipf("skipping: %v", err) - } - - // Check that the checktest symbols are initialized properly. -diff --git a/src/crypto/mlkem/mlkem1024.go b/src/crypto/mlkem/mlkem1024.go -index 530aacf00f..05bad1eb2a 100644 ---- a/src/crypto/mlkem/mlkem1024.go -+++ b/src/crypto/mlkem/mlkem1024.go -@@ -91,6 +91,6 @@ func (ek *EncapsulationKey1024) Bytes() []byte { - // encapsulation key, drawing random bytes from crypto/rand. - // - // The shared key must be kept secret. --func (ek *EncapsulationKey1024) Encapsulate() (ciphertext, sharedKey []byte) { -+func (ek *EncapsulationKey1024) Encapsulate() (sharedKey, ciphertext []byte) { - return ek.key.Encapsulate() - } -diff --git a/src/crypto/mlkem/mlkem768.go b/src/crypto/mlkem/mlkem768.go -index d6f5c94171..c367c551e6 100644 ---- a/src/crypto/mlkem/mlkem768.go -+++ b/src/crypto/mlkem/mlkem768.go -@@ -101,6 +101,6 @@ func (ek *EncapsulationKey768) Bytes() []byte { - // encapsulation key, drawing random bytes from crypto/rand. - // - // The shared key must be kept secret. --func (ek *EncapsulationKey768) Encapsulate() (ciphertext, sharedKey []byte) { -+func (ek *EncapsulationKey768) Encapsulate() (sharedKey, ciphertext []byte) { - return ek.key.Encapsulate() - } -diff --git a/src/crypto/mlkem/mlkem_test.go b/src/crypto/mlkem/mlkem_test.go -index ddc52dab97..207d6d48c3 100644 ---- a/src/crypto/mlkem/mlkem_test.go -+++ b/src/crypto/mlkem/mlkem_test.go -@@ -43,7 +43,7 @@ func testRoundTrip[E encapsulationKey, D decapsulationKey[E]]( - t.Fatal(err) - } - ek := dk.EncapsulationKey() -- c, Ke := ek.Encapsulate() -+ Ke, c := ek.Encapsulate() - Kd, err := dk.Decapsulate(c) - if err != nil { - t.Fatal(err) -@@ -66,7 +66,7 @@ func testRoundTrip[E encapsulationKey, D decapsulationKey[E]]( - if !bytes.Equal(dk.Bytes(), dk1.Bytes()) { - t.Fail() - } -- c1, Ke1 := ek1.Encapsulate() -+ Ke1, c1 := ek1.Encapsulate() - Kd1, err := dk1.Decapsulate(c1) - if err != nil { - t.Fatal(err) -@@ -86,7 +86,7 @@ func testRoundTrip[E encapsulationKey, D decapsulationKey[E]]( - t.Fail() - } - -- c2, Ke2 := dk.EncapsulationKey().Encapsulate() -+ Ke2, c2 := dk.EncapsulationKey().Encapsulate() - if bytes.Equal(c, c2) { - t.Fail() - } -@@ -115,7 +115,7 @@ func testBadLengths[E encapsulationKey, D decapsulationKey[E]]( - } - ek := dk.EncapsulationKey() - ekBytes := dk.EncapsulationKey().Bytes() -- c, _ := ek.Encapsulate() -+ _, c := ek.Encapsulate() - - for i := 0; i < len(dkBytes)-1; i++ { - if _, err := newDecapsulationKey(dkBytes[:i]); err == nil { -@@ -189,7 +189,7 @@ func TestAccumulated(t *testing.T) { - o.Write(ek.Bytes()) - - s.Read(msg[:]) -- ct, k := ek.key.EncapsulateInternal(&msg) -+ k, ct := ek.key.EncapsulateInternal(&msg) - o.Write(ct) - o.Write(k) - -@@ -244,7 +244,7 @@ func BenchmarkEncaps(b *testing.B) { - if err != nil { - b.Fatal(err) - } -- c, K := ek.key.EncapsulateInternal(&m) -+ K, c := ek.key.EncapsulateInternal(&m) - sink ^= c[0] ^ K[0] - } - } -@@ -255,7 +255,7 @@ func BenchmarkDecaps(b *testing.B) { - b.Fatal(err) - } - ek := dk.EncapsulationKey() -- c, _ := ek.Encapsulate() -+ _, c := ek.Encapsulate() - b.ResetTimer() - for i := 0; i < b.N; i++ { - K, _ := dk.Decapsulate(c) -@@ -270,7 +270,7 @@ func BenchmarkRoundTrip(b *testing.B) { - } - ek := dk.EncapsulationKey() - ekBytes := ek.Bytes() -- c, _ := ek.Encapsulate() -+ _, c := ek.Encapsulate() - if err != nil { - b.Fatal(err) - } -@@ -296,7 +296,7 @@ func BenchmarkRoundTrip(b *testing.B) { - if err != nil { - b.Fatal(err) - } -- cS, Ks := ek.Encapsulate() -+ Ks, cS := ek.Encapsulate() - if err != nil { - b.Fatal(err) - } -diff --git a/src/crypto/pbkdf2/pbkdf2.go b/src/crypto/pbkdf2/pbkdf2.go -index 0fdd9e822d..d40daab5e5 100644 ---- a/src/crypto/pbkdf2/pbkdf2.go -+++ b/src/crypto/pbkdf2/pbkdf2.go -@@ -2,20 +2,12 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --/* --Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC --2898 / PKCS #5 v2.0. -- --A key derivation function is useful when encrypting data based on a password --or any other not-fully-random data. It uses a pseudorandom function to derive --a secure encryption key based on the password. -- --While v2.0 of the standard defines only one pseudorandom function to use, --HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved --Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To --choose, you can pass the `New` functions from the different SHA packages to --pbkdf2.Key. --*/ -+// Package pbkdf2 implements the key derivation function PBKDF2 as defined in -+// RFC 8018 (PKCS #5 v2.1). -+// -+// A key derivation function is useful when encrypting data based on a password -+// or any other not-fully-random data. It uses a pseudorandom function to derive -+// a secure encryption key based on the password. - package pbkdf2 - - import ( -diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go -index 2474ab82df..2535661040 100644 ---- a/src/crypto/rsa/rsa_test.go -+++ b/src/crypto/rsa/rsa_test.go -@@ -101,7 +101,7 @@ func TestImpossibleKeyGeneration(t *testing.T) { - // This test ensures that trying to generate or validate toy RSA keys - // doesn't enter an infinite loop or panic. - t.Setenv("GODEBUG", "rsa1024min=0") -- for i := 0; i < 128; i++ { -+ for i := 0; i < 32; i++ { - GenerateKey(rand.Reader, i) - GenerateMultiPrimeKey(rand.Reader, 3, i) - GenerateMultiPrimeKey(rand.Reader, 4, i) -@@ -184,7 +184,7 @@ func TestEverything(t *testing.T) { - } - - t.Setenv("GODEBUG", "rsa1024min=0") -- min := 128 -+ min := 32 - max := 560 // any smaller than this and not all tests will run - if *allFlag { - max = 2048 -diff --git a/src/crypto/tls/bogo_config.json b/src/crypto/tls/bogo_config.json -index 1c313ec81e..32969a3fb5 100644 ---- a/src/crypto/tls/bogo_config.json -+++ b/src/crypto/tls/bogo_config.json -@@ -246,5 +246,8 @@ - 25, - 29, - 4588 -- ] -+ ], -+ "ErrorMap": { -+ ":ECH_REJECTED:": "tls: server rejected ECH" -+ } - } -diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go -index f98d24b879..d6942d2ef1 100644 ---- a/src/crypto/tls/common.go -+++ b/src/crypto/tls/common.go -@@ -456,7 +456,7 @@ type ClientHelloInfo struct { - SupportedVersions []uint16 - - // Extensions lists the IDs of the extensions presented by the client -- // in the client hello. -+ // in the ClientHello. - Extensions []uint16 - - // Conn is the underlying net.Conn for the connection. Do not read -@@ -821,7 +821,7 @@ type Config struct { - - // EncryptedClientHelloRejectionVerify, if not nil, is called when ECH is - // rejected by the remote server, in order to verify the ECH provider -- // certificate in the outer Client Hello. If it returns a non-nil error, the -+ // certificate in the outer ClientHello. If it returns a non-nil error, the - // handshake is aborted and that error results. - // - // On the server side this field is not used. -diff --git a/src/crypto/tls/ech.go b/src/crypto/tls/ech.go -index 55d52179c2..d9795b4ee2 100644 ---- a/src/crypto/tls/ech.go -+++ b/src/crypto/tls/ech.go -@@ -378,7 +378,7 @@ func decodeInnerClientHello(outer *clientHelloMsg, encoded []byte) (*clientHello - } - - if !bytes.Equal(inner.encryptedClientHello, []byte{uint8(innerECHExt)}) { -- return nil, errors.New("tls: client sent invalid encrypted_client_hello extension") -+ return nil, errInvalidECHExt - } - - if len(inner.supportedVersions) != 1 || (len(inner.supportedVersions) >= 1 && inner.supportedVersions[0] != VersionTLS13) { -@@ -481,6 +481,7 @@ func (e *ECHRejectionError) Error() string { - } - - var errMalformedECHExt = errors.New("tls: malformed encrypted_client_hello extension") -+var errInvalidECHExt = errors.New("tls: client sent invalid encrypted_client_hello extension") - - type echExtType uint8 - -@@ -507,7 +508,7 @@ func parseECHExt(ext []byte) (echType echExtType, cs echCipher, configID uint8, - return echType, cs, 0, nil, nil, nil - } - if echType != outerECHExt { -- err = errMalformedECHExt -+ err = errInvalidECHExt - return - } - if !s.ReadUint16(&cs.KDFID) { -@@ -549,8 +550,13 @@ func marshalEncryptedClientHelloConfigList(configs []EncryptedClientHelloKey) ([ - func (c *Conn) processECHClientHello(outer *clientHelloMsg) (*clientHelloMsg, *echServerContext, error) { - echType, echCiphersuite, configID, encap, payload, err := parseECHExt(outer.encryptedClientHello) - if err != nil { -- c.sendAlert(alertDecodeError) -- return nil, nil, errors.New("tls: client sent invalid encrypted_client_hello extension") -+ if errors.Is(err, errInvalidECHExt) { -+ c.sendAlert(alertIllegalParameter) -+ } else { -+ c.sendAlert(alertDecodeError) -+ } -+ -+ return nil, nil, errInvalidECHExt - } - - if echType == innerECHExt { -@@ -597,7 +603,7 @@ func (c *Conn) processECHClientHello(outer *clientHelloMsg) (*clientHelloMsg, *e - echInner, err := decodeInnerClientHello(outer, encodedInner) - if err != nil { - c.sendAlert(alertIllegalParameter) -- return nil, nil, errors.New("tls: client sent invalid encrypted_client_hello extension") -+ return nil, nil, errInvalidECHExt - } - - c.echAccepted = true -diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go -index ecc62ff2ed..38bd417a0d 100644 ---- a/src/crypto/tls/handshake_client.go -+++ b/src/crypto/tls/handshake_client.go -@@ -260,6 +260,7 @@ type echClientContext struct { - kdfID uint16 - aeadID uint16 - echRejected bool -+ retryConfigs []byte - } - - func (c *Conn) clientHandshake(ctx context.Context) (err error) { -@@ -944,7 +945,7 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { - } - - // checkALPN ensure that the server's choice of ALPN protocol is compatible with --// the protocols that we advertised in the Client Hello. -+// the protocols that we advertised in the ClientHello. - func checkALPN(clientProtos []string, serverProto string, quic bool) error { - if serverProto == "" { - if quic && len(clientProtos) > 0 { -diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go -index bb164bba55..bc54475fa4 100644 ---- a/src/crypto/tls/handshake_client_test.go -+++ b/src/crypto/tls/handshake_client_test.go -@@ -856,6 +856,7 @@ func testResumption(t *testing.T, version uint16) { - MaxVersion: version, - CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, - Certificates: testCertificates, -+ Time: testTime, - } - - issuer, err := x509.ParseCertificate(testRSA2048CertificateIssuer) -@@ -872,6 +873,7 @@ func testResumption(t *testing.T, version uint16) { - ClientSessionCache: NewLRUClientSessionCache(32), - RootCAs: rootCAs, - ServerName: "example.golang", -+ Time: testTime, - } - - testResumeState := func(test string, didResume bool) { -@@ -918,7 +920,7 @@ func testResumption(t *testing.T, version uint16) { - - // An old session ticket is replaced with a ticket encrypted with a fresh key. - ticket = getTicket() -- serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } -+ serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) } - testResumeState("ResumeWithOldTicket", true) - if bytes.Equal(ticket, getTicket()) { - t.Fatal("old first ticket matches the fresh one") -@@ -926,13 +928,13 @@ func testResumption(t *testing.T, version uint16) { - - // Once the session master secret is expired, a full handshake should occur. - ticket = getTicket() -- serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } -+ serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + time.Minute) } - testResumeState("ResumeWithExpiredTicket", false) - if bytes.Equal(ticket, getTicket()) { - t.Fatal("expired first ticket matches the fresh one") - } - -- serverConfig.Time = func() time.Time { return time.Now() } // reset the time back -+ serverConfig.Time = testTime // reset the time back - key1 := randomKey() - serverConfig.SetSessionTicketKeys([][32]byte{key1}) - -@@ -949,11 +951,11 @@ func testResumption(t *testing.T, version uint16) { - testResumeState("KeyChangeFinish", true) - - // Age the session ticket a bit, but not yet expired. -- serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) } -+ serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) } - testResumeState("OldSessionTicket", true) - ticket = getTicket() - // Expire the session ticket, which would force a full handshake. -- serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) } -+ serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + 2*time.Minute) } - testResumeState("ExpiredSessionTicket", false) - if bytes.Equal(ticket, getTicket()) { - t.Fatal("new ticket wasn't provided after old ticket expired") -@@ -961,7 +963,7 @@ func testResumption(t *testing.T, version uint16) { - - // Age the session ticket a bit at a time, but don't expire it. - d := 0 * time.Hour -- serverConfig.Time = func() time.Time { return time.Now().Add(d) } -+ serverConfig.Time = func() time.Time { return testTime().Add(d) } - deleteTicket() - testResumeState("GetFreshSessionTicket", false) - for i := 0; i < 13; i++ { -@@ -972,7 +974,7 @@ func testResumption(t *testing.T, version uint16) { - // handshake occurs for TLS 1.2. Resumption should still occur for - // TLS 1.3 since the client should be using a fresh ticket sent over - // by the server. -- d += 12 * time.Hour -+ d += 12*time.Hour + time.Minute - if version == VersionTLS13 { - testResumeState("ExpiredSessionTicket", true) - } else { -@@ -988,6 +990,7 @@ func testResumption(t *testing.T, version uint16) { - MaxVersion: version, - CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, - Certificates: testCertificates, -+ Time: testTime, - } - serverConfig.SetSessionTicketKeys([][32]byte{key2}) - -@@ -1013,6 +1016,7 @@ func testResumption(t *testing.T, version uint16) { - CurvePreferences: []CurveID{CurveP521, CurveP384, CurveP256}, - MaxVersion: version, - Certificates: testCertificates, -+ Time: testTime, - } - testResumeState("InitialHandshake", false) - testResumeState("WithHelloRetryRequest", true) -@@ -1022,6 +1026,7 @@ func testResumption(t *testing.T, version uint16) { - MaxVersion: version, - CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, - Certificates: testCertificates, -+ Time: testTime, - } - } - -@@ -1743,6 +1748,7 @@ func testVerifyConnection(t *testing.T, version uint16) { - serverConfig := &Config{ - MaxVersion: version, - Certificates: testCertificates, -+ Time: testTime, - ClientCAs: rootCAs, - NextProtos: []string{"protocol1"}, - } -@@ -1756,6 +1762,7 @@ func testVerifyConnection(t *testing.T, version uint16) { - RootCAs: rootCAs, - ServerName: "example.golang", - Certificates: testCertificates, -+ Time: testTime, - NextProtos: []string{"protocol1"}, - } - test.configureClient(clientConfig, &clientCalled) -@@ -1799,8 +1806,6 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { - rootCAs := x509.NewCertPool() - rootCAs.AddCert(issuer) - -- now := func() time.Time { return time.Unix(1476984729, 0) } -- - sentinelErr := errors.New("TestVerifyPeerCertificate") - - verifyPeerCertificateCallback := func(called *bool, rawCerts [][]byte, validatedChains [][]*x509.Certificate) error { -@@ -2046,7 +2051,7 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { - config.ServerName = "example.golang" - config.ClientAuth = RequireAndVerifyClientCert - config.ClientCAs = rootCAs -- config.Time = now -+ config.Time = testTime - config.MaxVersion = version - config.Certificates = make([]Certificate, 1) - config.Certificates[0].Certificate = [][]byte{testRSA2048Certificate} -@@ -2064,7 +2069,7 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) { - config.Certificates = []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} - config.ServerName = "example.golang" - config.RootCAs = rootCAs -- config.Time = now -+ config.Time = testTime - config.MaxVersion = version - test.configureClient(config, &clientCalled) - clientErr := Client(c, config).Handshake() -@@ -2379,7 +2384,7 @@ func testGetClientCertificate(t *testing.T, version uint16) { - serverConfig.RootCAs = x509.NewCertPool() - serverConfig.RootCAs.AddCert(issuer) - serverConfig.ClientCAs = serverConfig.RootCAs -- serverConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } -+ serverConfig.Time = testTime - serverConfig.MaxVersion = version - - clientConfig := testConfig.Clone() -@@ -2562,6 +2567,7 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) { - ClientSessionCache: NewLRUClientSessionCache(32), - ServerName: "example.golang", - RootCAs: roots, -+ Time: testTime, - } - serverConfig := testConfig.Clone() - serverConfig.Certificates = []Certificate{{Certificate: [][]byte{testRSA2048Certificate}, PrivateKey: testRSA2048PrivateKey}} -diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go -index 38c6025db7..c0396e7579 100644 ---- a/src/crypto/tls/handshake_client_tls13.go -+++ b/src/crypto/tls/handshake_client_tls13.go -@@ -85,7 +85,6 @@ func (hs *clientHandshakeStateTLS13) handshake() error { - } - } - -- var echRetryConfigList []byte - if hs.echContext != nil { - confTranscript := cloneHash(hs.echContext.innerTranscript, hs.suite.hash) - confTranscript.Write(hs.serverHello.original[:30]) -@@ -114,9 +113,6 @@ func (hs *clientHandshakeStateTLS13) handshake() error { - } - } else { - hs.echContext.echRejected = true -- // If the server sent us retry configs, we'll return these to -- // the user so they can update their Config. -- echRetryConfigList = hs.serverHello.encryptedClientHello - } - } - -@@ -155,7 +151,7 @@ func (hs *clientHandshakeStateTLS13) handshake() error { - - if hs.echContext != nil && hs.echContext.echRejected { - c.sendAlert(alertECHRequired) -- return &ECHRejectionError{echRetryConfigList} -+ return &ECHRejectionError{hs.echContext.retryConfigs} - } - - c.isHandshakeComplete.Store(true) -@@ -601,9 +597,13 @@ func (hs *clientHandshakeStateTLS13) readServerParameters() error { - return errors.New("tls: server accepted 0-RTT with the wrong ALPN") - } - } -- if hs.echContext != nil && !hs.echContext.echRejected && encryptedExtensions.echRetryConfigs != nil { -- c.sendAlert(alertUnsupportedExtension) -- return errors.New("tls: server sent encrypted client hello retry configs after accepting encrypted client hello") -+ if hs.echContext != nil { -+ if hs.echContext.echRejected { -+ hs.echContext.retryConfigs = encryptedExtensions.echRetryConfigs -+ } else if encryptedExtensions.echRetryConfigs != nil { -+ c.sendAlert(alertUnsupportedExtension) -+ return errors.New("tls: server sent encrypted client hello retry configs after accepting encrypted client hello") -+ } - } - - return nil -diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go -index fa00d7b741..6c6141c421 100644 ---- a/src/crypto/tls/handshake_messages.go -+++ b/src/crypto/tls/handshake_messages.go -@@ -97,7 +97,7 @@ type clientHelloMsg struct { - pskBinders [][]byte - quicTransportParameters []byte - encryptedClientHello []byte -- // extensions are only populated on the servers-ide of a handshake -+ // extensions are only populated on the server-side of a handshake - extensions []uint16 - } - -diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go -index 29a802d54b..f533023afb 100644 ---- a/src/crypto/tls/handshake_server_test.go -+++ b/src/crypto/tls/handshake_server_test.go -@@ -519,6 +519,7 @@ func testCrossVersionResume(t *testing.T, version uint16) { - serverConfig := &Config{ - CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, - Certificates: testConfig.Certificates, -+ Time: testTime, - } - clientConfig := &Config{ - CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, -@@ -526,6 +527,7 @@ func testCrossVersionResume(t *testing.T, version uint16) { - ClientSessionCache: NewLRUClientSessionCache(1), - ServerName: "servername", - MinVersion: VersionTLS12, -+ Time: testTime, - } - - // Establish a session at TLS 1.3. -diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go -index 3552d89ba3..76fff6974e 100644 ---- a/src/crypto/tls/handshake_server_tls13.go -+++ b/src/crypto/tls/handshake_server_tls13.go -@@ -280,7 +280,7 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error { - c.sendAlert(alertIllegalParameter) - return errors.New("tls: invalid X25519MLKEM768 client key share") - } -- ciphertext, mlkemSharedSecret := k.Encapsulate() -+ mlkemSharedSecret, ciphertext := k.Encapsulate() - // draft-kwiatkowski-tls-ecdhe-mlkem-02, Section 3.1.3: "For - // X25519MLKEM768, the shared secret is the concatenation of the ML-KEM - // shared secret and the X25519 shared secret. The shared secret is 64 -diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go -index 5a9c24fb83..ea8ac6fc83 100644 ---- a/src/crypto/tls/handshake_test.go -+++ b/src/crypto/tls/handshake_test.go -@@ -522,6 +522,11 @@ func fromHex(s string) []byte { - return b - } - -+// testTime is 2016-10-20T17:32:09.000Z, which is within the validity period of -+// [testRSACertificate], [testRSACertificateIssuer], [testRSA2048Certificate], -+// [testRSA2048CertificateIssuer], and [testECDSACertificate]. -+var testTime = func() time.Time { return time.Unix(1476984729, 0) } -+ - var testRSACertificate = fromHex("3082024b308201b4a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301a310b3009060355040a1302476f310b300906035504031302476f30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a38193308190300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b30190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b0500038181009d30cc402b5b50a061cbbae55358e1ed8328a9581aa938a495a1ac315a1a84663d43d32dd90bf297dfd320643892243a00bccf9c7db74020015faad3166109a276fd13c3cce10c5ceeb18782f16c04ed73bbb343778d0c1cf10fa1d8408361c94c722b9daedb4606064df4c1b33ec0d1bd42d4dbfe3d1360845c21d33be9fae7") - - var testRSACertificateIssuer = fromHex("3082021930820182a003020102020900ca5e4e811a965964300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f7430819f300d06092a864886f70d010101050003818d0030818902818100d667b378bb22f34143b6cd2008236abefaf2852adf3ab05e01329e2c14834f5105df3f3073f99dab5442d45ee5f8f57b0111c8cb682fbb719a86944eebfffef3406206d898b8c1b1887797c9c5006547bb8f00e694b7a063f10839f269f2c34fff7a1f4b21fbcd6bfdfb13ac792d1d11f277b5c5b48600992203059f2a8f8cc50203010001a35d305b300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff30190603551d0e041204104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b050003818100c1154b4bab5266221f293766ae4138899bd4c5e36b13cee670ceeaa4cbdf4f6679017e2fe649765af545749fe4249418a56bd38a04b81e261f5ce86b8d5c65413156a50d12449554748c59a30c515bc36a59d38bddf51173e899820b282e40aa78c806526fd184fb6b4cf186ec728edffa585440d2b3225325f7ab580e87dd76") -diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go -index 51cd2b91bd..76a9a222a9 100644 ---- a/src/crypto/tls/tls_test.go -+++ b/src/crypto/tls/tls_test.go -@@ -1158,8 +1158,6 @@ func TestConnectionState(t *testing.T) { - rootCAs := x509.NewCertPool() - rootCAs.AddCert(issuer) - -- now := func() time.Time { return time.Unix(1476984729, 0) } -- - const alpnProtocol = "golang" - const serverName = "example.golang" - var scts = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")} -@@ -1175,7 +1173,7 @@ func TestConnectionState(t *testing.T) { - } - t.Run(name, func(t *testing.T) { - config := &Config{ -- Time: now, -+ Time: testTime, - Rand: zeroSource{}, - Certificates: make([]Certificate, 1), - MaxVersion: v, -@@ -1810,7 +1808,7 @@ func testVerifyCertificates(t *testing.T, version uint16) { - var serverVerifyPeerCertificates, clientVerifyPeerCertificates bool - - clientConfig := testConfig.Clone() -- clientConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } -+ clientConfig.Time = testTime - clientConfig.MaxVersion = version - clientConfig.MinVersion = version - clientConfig.RootCAs = rootCAs -diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go -index 958ed9971d..89bd70b5b2 100644 ---- a/src/debug/elf/file.go -+++ b/src/debug/elf/file.go -@@ -209,22 +209,13 @@ type Symbol struct { - Name string - Info, Other byte - -- // VersionScope describes the version in which the symbol is defined. -- // This is only set for the dynamic symbol table. -- // When no symbol versioning information is available, -- // this is VersionScopeNone. -- VersionScope SymbolVersionScope -- // VersionIndex is the version index. -- // This is only set if VersionScope is VersionScopeSpecific or -- // VersionScopeHidden. This is only set for the dynamic symbol table. -- // This index will match either [DynamicVersion.Index] -- // in the slice returned by [File.DynamicVersions], -- // or [DynamicVersiondep.Index] in the Needs field -- // of the elements of the slice returned by [File.DynamicVersionNeeds]. -- // In general, a defined symbol will have an index referring -- // to DynamicVersions, and an undefined symbol will have an index -- // referring to some version in DynamicVersionNeeds. -- VersionIndex int16 -+ // HasVersion reports whether the symbol has any version information. -+ // This will only be true for the dynamic symbol table. -+ HasVersion bool -+ // VersionIndex is the symbol's version index. -+ // Use the methods of the [VersionIndex] type to access it. -+ // This field is only meaningful if HasVersion is true. -+ VersionIndex VersionIndex - - Section SectionIndex - Value, Size uint64 -@@ -678,7 +669,6 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { - symbols[i].Name = str - symbols[i].Info = sym.Info - symbols[i].Other = sym.Other -- symbols[i].VersionIndex = -1 - symbols[i].Section = SectionIndex(sym.Shndx) - symbols[i].Value = uint64(sym.Value) - symbols[i].Size = uint64(sym.Size) -@@ -726,7 +716,6 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) { - symbols[i].Name = str - symbols[i].Info = sym.Info - symbols[i].Other = sym.Other -- symbols[i].VersionIndex = -1 - symbols[i].Section = SectionIndex(sym.Shndx) - symbols[i].Value = sym.Value - symbols[i].Size = sym.Size -@@ -1473,7 +1462,7 @@ func (f *File) DynamicSymbols() ([]Symbol, error) { - } - if hasVersions { - for i := range sym { -- sym[i].VersionIndex, sym[i].Version, sym[i].Library, sym[i].VersionScope = f.gnuVersion(i) -+ sym[i].HasVersion, sym[i].VersionIndex, sym[i].Version, sym[i].Library = f.gnuVersion(i) - } - } - return sym, nil -@@ -1502,23 +1491,37 @@ func (f *File) ImportedSymbols() ([]ImportedSymbol, error) { - if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF { - all = append(all, ImportedSymbol{Name: s.Name}) - sym := &all[len(all)-1] -- _, sym.Version, sym.Library, _ = f.gnuVersion(i) -+ _, _, sym.Version, sym.Library = f.gnuVersion(i) - } - } - return all, nil - } - --// SymbolVersionScope describes the version in which a [Symbol] is defined. --// This is only used for the dynamic symbol table. --type SymbolVersionScope byte -+// VersionIndex is the type of a [Symbol] version index. -+type VersionIndex uint16 - --const ( -- VersionScopeNone SymbolVersionScope = iota // no symbol version available -- VersionScopeLocal // symbol has local scope -- VersionScopeGlobal // symbol has global scope and is in the base version -- VersionScopeSpecific // symbol has global scope and is in the version given by VersionIndex -- VersionScopeHidden // symbol is in the version given by VersionIndex, and is hidden --) -+// IsHidden reports whether the symbol is hidden within the version. -+// This means that the symbol can only be seen by specifying the exact version. -+func (vi VersionIndex) IsHidden() bool { -+ return vi&0x8000 != 0 -+} -+ -+// Index returns the version index. -+// If this is the value 0, it means that the symbol is local, -+// and is not visible externally. -+// If this is the value 1, it means that the symbol is in the base version, -+// and has no specific version; it may or may not match a -+// [DynamicVersion.Index] in the slice returned by [File.DynamicVersions]. -+// Other values will match either [DynamicVersion.Index] -+// in the slice returned by [File.DynamicVersions], -+// or [DynamicVersionDep.Index] in the Needs field -+// of the elements of the slice returned by [File.DynamicVersionNeeds]. -+// In general, a defined symbol will have an index referring -+// to DynamicVersions, and an undefined symbol will have an index -+// referring to some version in DynamicVersionNeeds. -+func (vi VersionIndex) Index() uint16 { -+ return uint16(vi & 0x7fff) -+} - - // DynamicVersion is a version defined by a dynamic object. - // This describes entries in the ELF SHT_GNU_verdef section. -@@ -1752,45 +1755,38 @@ func (f *File) gnuVersionInit(str []byte) (bool, error) { - - // gnuVersion adds Library and Version information to sym, - // which came from offset i of the symbol table. --func (f *File) gnuVersion(i int) (versionIndex int16, version string, library string, versionFlags SymbolVersionScope) { -+func (f *File) gnuVersion(i int) (hasVersion bool, versionIndex VersionIndex, version string, library string) { - // Each entry is two bytes; skip undef entry at beginning. - i = (i + 1) * 2 - if i >= len(f.gnuVersym) { -- return -1, "", "", VersionScopeNone -+ return false, 0, "", "" - } - s := f.gnuVersym[i:] - if len(s) < 2 { -- return -1, "", "", VersionScopeNone -- } -- j := int32(f.ByteOrder.Uint16(s)) -- ndx := int16(j & 0x7fff) -- -- if j == 0 { -- return ndx, "", "", VersionScopeLocal -- } else if j == 1 { -- return ndx, "", "", VersionScopeGlobal -+ return false, 0, "", "" - } -+ vi := VersionIndex(f.ByteOrder.Uint16(s)) -+ ndx := vi.Index() - -- scope := VersionScopeSpecific -- if j&0x8000 != 0 { -- scope = VersionScopeHidden -+ if ndx == 0 || ndx == 1 { -+ return true, vi, "", "" - } - - for _, v := range f.dynVerNeeds { - for _, n := range v.Needs { -- if uint16(ndx) == n.Index { -- return ndx, n.Dep, v.Name, scope -+ if ndx == n.Index { -+ return true, vi, n.Dep, v.Name - } - } - } - - for _, v := range f.dynVers { -- if uint16(ndx) == v.Index { -- return ndx, v.Name, "", scope -+ if ndx == v.Index { -+ return true, vi, v.Name, "" - } - } - -- return -1, "", "", VersionScopeNone -+ return false, 0, "", "" - } - - // ImportedLibraries returns the names of all libraries -diff --git a/src/debug/elf/file_test.go b/src/debug/elf/file_test.go -index 72e4558868..1fdbbad04d 100644 ---- a/src/debug/elf/file_test.go -+++ b/src/debug/elf/file_test.go -@@ -78,80 +78,80 @@ var fileTests = []fileTest{ - }, - []string{"libc.so.6"}, - []Symbol{ -- {"", 3, 0, VersionScopeNone, -1, 1, 134512852, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 2, 134512876, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 3, 134513020, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 4, 134513292, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 5, 134513480, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 6, 134513512, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 7, 134513532, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 8, 134513612, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 9, 134513996, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 10, 134514008, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 11, 134518268, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 12, 134518280, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 13, 134518284, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 14, 134518436, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 15, 134518444, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 16, 134518452, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 17, 134518456, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 18, 134518484, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 19, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 20, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 21, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 22, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 23, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 24, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 25, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 26, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 27, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 28, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 29, 0, 0, "", ""}, -- {"crt1.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"__CTOR_LIST__", 1, 0, VersionScopeNone, -1, 14, 134518436, 0, "", ""}, -- {"__DTOR_LIST__", 1, 0, VersionScopeNone, -1, 15, 134518444, 0, "", ""}, -- {"__EH_FRAME_BEGIN__", 1, 0, VersionScopeNone, -1, 12, 134518280, 0, "", ""}, -- {"__JCR_LIST__", 1, 0, VersionScopeNone, -1, 16, 134518452, 0, "", ""}, -- {"p.0", 1, 0, VersionScopeNone, -1, 11, 134518276, 0, "", ""}, -- {"completed.1", 1, 0, VersionScopeNone, -1, 18, 134518484, 1, "", ""}, -- {"__do_global_dtors_aux", 2, 0, VersionScopeNone, -1, 8, 134513760, 0, "", ""}, -- {"object.2", 1, 0, VersionScopeNone, -1, 18, 134518488, 24, "", ""}, -- {"frame_dummy", 2, 0, VersionScopeNone, -1, 8, 134513836, 0, "", ""}, -- {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"__CTOR_END__", 1, 0, VersionScopeNone, -1, 14, 134518440, 0, "", ""}, -- {"__DTOR_END__", 1, 0, VersionScopeNone, -1, 15, 134518448, 0, "", ""}, -- {"__FRAME_END__", 1, 0, VersionScopeNone, -1, 12, 134518280, 0, "", ""}, -- {"__JCR_END__", 1, 0, VersionScopeNone, -1, 16, 134518452, 0, "", ""}, -- {"__do_global_ctors_aux", 2, 0, VersionScopeNone, -1, 8, 134513960, 0, "", ""}, -- {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"printf", 18, 0, VersionScopeNone, -1, 0, 0, 44, "", ""}, -- {"_DYNAMIC", 17, 0, VersionScopeNone, -1, 65521, 134518284, 0, "", ""}, -- {"__dso_handle", 17, 2, VersionScopeNone, -1, 11, 134518272, 0, "", ""}, -- {"_init", 18, 0, VersionScopeNone, -1, 6, 134513512, 0, "", ""}, -- {"environ", 17, 0, VersionScopeNone, -1, 18, 134518512, 4, "", ""}, -- {"__deregister_frame_info", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, -- {"__progname", 17, 0, VersionScopeNone, -1, 11, 134518268, 4, "", ""}, -- {"_start", 18, 0, VersionScopeNone, -1, 8, 134513612, 145, "", ""}, -- {"__bss_start", 16, 0, VersionScopeNone, -1, 65521, 134518484, 0, "", ""}, -- {"main", 18, 0, VersionScopeNone, -1, 8, 134513912, 46, "", ""}, -- {"_init_tls", 18, 0, VersionScopeNone, -1, 0, 0, 5, "", ""}, -- {"_fini", 18, 0, VersionScopeNone, -1, 9, 134513996, 0, "", ""}, -- {"atexit", 18, 0, VersionScopeNone, -1, 0, 0, 43, "", ""}, -- {"_edata", 16, 0, VersionScopeNone, -1, 65521, 134518484, 0, "", ""}, -- {"_GLOBAL_OFFSET_TABLE_", 17, 0, VersionScopeNone, -1, 65521, 134518456, 0, "", ""}, -- {"_end", 16, 0, VersionScopeNone, -1, 65521, 134518516, 0, "", ""}, -- {"exit", 18, 0, VersionScopeNone, -1, 0, 0, 68, "", ""}, -- {"_Jv_RegisterClasses", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, -- {"__register_frame_info", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 1, 134512852, 0, "", ""}, -+ {"", 3, 0, false, 0, 2, 134512876, 0, "", ""}, -+ {"", 3, 0, false, 0, 3, 134513020, 0, "", ""}, -+ {"", 3, 0, false, 0, 4, 134513292, 0, "", ""}, -+ {"", 3, 0, false, 0, 5, 134513480, 0, "", ""}, -+ {"", 3, 0, false, 0, 6, 134513512, 0, "", ""}, -+ {"", 3, 0, false, 0, 7, 134513532, 0, "", ""}, -+ {"", 3, 0, false, 0, 8, 134513612, 0, "", ""}, -+ {"", 3, 0, false, 0, 9, 134513996, 0, "", ""}, -+ {"", 3, 0, false, 0, 10, 134514008, 0, "", ""}, -+ {"", 3, 0, false, 0, 11, 134518268, 0, "", ""}, -+ {"", 3, 0, false, 0, 12, 134518280, 0, "", ""}, -+ {"", 3, 0, false, 0, 13, 134518284, 0, "", ""}, -+ {"", 3, 0, false, 0, 14, 134518436, 0, "", ""}, -+ {"", 3, 0, false, 0, 15, 134518444, 0, "", ""}, -+ {"", 3, 0, false, 0, 16, 134518452, 0, "", ""}, -+ {"", 3, 0, false, 0, 17, 134518456, 0, "", ""}, -+ {"", 3, 0, false, 0, 18, 134518484, 0, "", ""}, -+ {"", 3, 0, false, 0, 19, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 20, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 21, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 22, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 23, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 24, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 25, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 26, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 27, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 28, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 29, 0, 0, "", ""}, -+ {"crt1.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"__CTOR_LIST__", 1, 0, false, 0, 14, 134518436, 0, "", ""}, -+ {"__DTOR_LIST__", 1, 0, false, 0, 15, 134518444, 0, "", ""}, -+ {"__EH_FRAME_BEGIN__", 1, 0, false, 0, 12, 134518280, 0, "", ""}, -+ {"__JCR_LIST__", 1, 0, false, 0, 16, 134518452, 0, "", ""}, -+ {"p.0", 1, 0, false, 0, 11, 134518276, 0, "", ""}, -+ {"completed.1", 1, 0, false, 0, 18, 134518484, 1, "", ""}, -+ {"__do_global_dtors_aux", 2, 0, false, 0, 8, 134513760, 0, "", ""}, -+ {"object.2", 1, 0, false, 0, 18, 134518488, 24, "", ""}, -+ {"frame_dummy", 2, 0, false, 0, 8, 134513836, 0, "", ""}, -+ {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"__CTOR_END__", 1, 0, false, 0, 14, 134518440, 0, "", ""}, -+ {"__DTOR_END__", 1, 0, false, 0, 15, 134518448, 0, "", ""}, -+ {"__FRAME_END__", 1, 0, false, 0, 12, 134518280, 0, "", ""}, -+ {"__JCR_END__", 1, 0, false, 0, 16, 134518452, 0, "", ""}, -+ {"__do_global_ctors_aux", 2, 0, false, 0, 8, 134513960, 0, "", ""}, -+ {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"printf", 18, 0, false, 0, 0, 0, 44, "", ""}, -+ {"_DYNAMIC", 17, 0, false, 0, 65521, 134518284, 0, "", ""}, -+ {"__dso_handle", 17, 2, false, 0, 11, 134518272, 0, "", ""}, -+ {"_init", 18, 0, false, 0, 6, 134513512, 0, "", ""}, -+ {"environ", 17, 0, false, 0, 18, 134518512, 4, "", ""}, -+ {"__deregister_frame_info", 32, 0, false, 0, 0, 0, 0, "", ""}, -+ {"__progname", 17, 0, false, 0, 11, 134518268, 4, "", ""}, -+ {"_start", 18, 0, false, 0, 8, 134513612, 145, "", ""}, -+ {"__bss_start", 16, 0, false, 0, 65521, 134518484, 0, "", ""}, -+ {"main", 18, 0, false, 0, 8, 134513912, 46, "", ""}, -+ {"_init_tls", 18, 0, false, 0, 0, 0, 5, "", ""}, -+ {"_fini", 18, 0, false, 0, 9, 134513996, 0, "", ""}, -+ {"atexit", 18, 0, false, 0, 0, 0, 43, "", ""}, -+ {"_edata", 16, 0, false, 0, 65521, 134518484, 0, "", ""}, -+ {"_GLOBAL_OFFSET_TABLE_", 17, 0, false, 0, 65521, 134518456, 0, "", ""}, -+ {"_end", 16, 0, false, 0, 65521, 134518516, 0, "", ""}, -+ {"exit", 18, 0, false, 0, 0, 0, 68, "", ""}, -+ {"_Jv_RegisterClasses", 32, 0, false, 0, 0, 0, 0, "", ""}, -+ {"__register_frame_info", 32, 0, false, 0, 0, 0, 0, "", ""}, - }, - }, - { -@@ -208,79 +208,79 @@ var fileTests = []fileTest{ - }, - []string{"libc.so.6"}, - []Symbol{ -- {"", 3, 0, VersionScopeNone, -1, 1, 4194816, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 2, 4194844, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 3, 4194880, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 4, 4194920, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 5, 4194952, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 6, 4195048, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 7, 4195110, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 8, 4195120, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 9, 4195152, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 10, 4195176, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 11, 4195224, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 12, 4195248, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 13, 4195296, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 14, 4195732, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 15, 4195748, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 16, 4195768, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 17, 4195808, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 18, 6293128, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 19, 6293144, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 20, 6293160, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 21, 6293168, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 22, 6293584, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 23, 6293592, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 24, 6293632, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 25, 6293656, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 26, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 27, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 28, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 29, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 30, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 31, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 32, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 33, 0, 0, "", ""}, -- {"init.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"initfini.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"call_gmon_start", 2, 0, VersionScopeNone, -1, 13, 4195340, 0, "", ""}, -- {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"__CTOR_LIST__", 1, 0, VersionScopeNone, -1, 18, 6293128, 0, "", ""}, -- {"__DTOR_LIST__", 1, 0, VersionScopeNone, -1, 19, 6293144, 0, "", ""}, -- {"__JCR_LIST__", 1, 0, VersionScopeNone, -1, 20, 6293160, 0, "", ""}, -- {"__do_global_dtors_aux", 2, 0, VersionScopeNone, -1, 13, 4195376, 0, "", ""}, -- {"completed.6183", 1, 0, VersionScopeNone, -1, 25, 6293656, 1, "", ""}, -- {"p.6181", 1, 0, VersionScopeNone, -1, 24, 6293648, 0, "", ""}, -- {"frame_dummy", 2, 0, VersionScopeNone, -1, 13, 4195440, 0, "", ""}, -- {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"__CTOR_END__", 1, 0, VersionScopeNone, -1, 18, 6293136, 0, "", ""}, -- {"__DTOR_END__", 1, 0, VersionScopeNone, -1, 19, 6293152, 0, "", ""}, -- {"__FRAME_END__", 1, 0, VersionScopeNone, -1, 17, 4195968, 0, "", ""}, -- {"__JCR_END__", 1, 0, VersionScopeNone, -1, 20, 6293160, 0, "", ""}, -- {"__do_global_ctors_aux", 2, 0, VersionScopeNone, -1, 13, 4195680, 0, "", ""}, -- {"initfini.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"_GLOBAL_OFFSET_TABLE_", 1, 2, VersionScopeNone, -1, 23, 6293592, 0, "", ""}, -- {"__init_array_end", 0, 2, VersionScopeNone, -1, 18, 6293124, 0, "", ""}, -- {"__init_array_start", 0, 2, VersionScopeNone, -1, 18, 6293124, 0, "", ""}, -- {"_DYNAMIC", 1, 2, VersionScopeNone, -1, 21, 6293168, 0, "", ""}, -- {"data_start", 32, 0, VersionScopeNone, -1, 24, 6293632, 0, "", ""}, -- {"__libc_csu_fini", 18, 0, VersionScopeNone, -1, 13, 4195520, 2, "", ""}, -- {"_start", 18, 0, VersionScopeNone, -1, 13, 4195296, 0, "", ""}, -- {"__gmon_start__", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, -- {"_Jv_RegisterClasses", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, -- {"puts@@GLIBC_2.2.5", 18, 0, VersionScopeNone, -1, 0, 0, 396, "", ""}, -- {"_fini", 18, 0, VersionScopeNone, -1, 14, 4195732, 0, "", ""}, -- {"__libc_start_main@@GLIBC_2.2.5", 18, 0, VersionScopeNone, -1, 0, 0, 450, "", ""}, -- {"_IO_stdin_used", 17, 0, VersionScopeNone, -1, 15, 4195748, 4, "", ""}, -- {"__data_start", 16, 0, VersionScopeNone, -1, 24, 6293632, 0, "", ""}, -- {"__dso_handle", 17, 2, VersionScopeNone, -1, 24, 6293640, 0, "", ""}, -- {"__libc_csu_init", 18, 0, VersionScopeNone, -1, 13, 4195536, 137, "", ""}, -- {"__bss_start", 16, 0, VersionScopeNone, -1, 65521, 6293656, 0, "", ""}, -- {"_end", 16, 0, VersionScopeNone, -1, 65521, 6293664, 0, "", ""}, -- {"_edata", 16, 0, VersionScopeNone, -1, 65521, 6293656, 0, "", ""}, -- {"main", 18, 0, VersionScopeNone, -1, 13, 4195480, 27, "", ""}, -- {"_init", 18, 0, VersionScopeNone, -1, 11, 4195224, 0, "", ""}, -+ {"", 3, 0, false, 0, 1, 4194816, 0, "", ""}, -+ {"", 3, 0, false, 0, 2, 4194844, 0, "", ""}, -+ {"", 3, 0, false, 0, 3, 4194880, 0, "", ""}, -+ {"", 3, 0, false, 0, 4, 4194920, 0, "", ""}, -+ {"", 3, 0, false, 0, 5, 4194952, 0, "", ""}, -+ {"", 3, 0, false, 0, 6, 4195048, 0, "", ""}, -+ {"", 3, 0, false, 0, 7, 4195110, 0, "", ""}, -+ {"", 3, 0, false, 0, 8, 4195120, 0, "", ""}, -+ {"", 3, 0, false, 0, 9, 4195152, 0, "", ""}, -+ {"", 3, 0, false, 0, 10, 4195176, 0, "", ""}, -+ {"", 3, 0, false, 0, 11, 4195224, 0, "", ""}, -+ {"", 3, 0, false, 0, 12, 4195248, 0, "", ""}, -+ {"", 3, 0, false, 0, 13, 4195296, 0, "", ""}, -+ {"", 3, 0, false, 0, 14, 4195732, 0, "", ""}, -+ {"", 3, 0, false, 0, 15, 4195748, 0, "", ""}, -+ {"", 3, 0, false, 0, 16, 4195768, 0, "", ""}, -+ {"", 3, 0, false, 0, 17, 4195808, 0, "", ""}, -+ {"", 3, 0, false, 0, 18, 6293128, 0, "", ""}, -+ {"", 3, 0, false, 0, 19, 6293144, 0, "", ""}, -+ {"", 3, 0, false, 0, 20, 6293160, 0, "", ""}, -+ {"", 3, 0, false, 0, 21, 6293168, 0, "", ""}, -+ {"", 3, 0, false, 0, 22, 6293584, 0, "", ""}, -+ {"", 3, 0, false, 0, 23, 6293592, 0, "", ""}, -+ {"", 3, 0, false, 0, 24, 6293632, 0, "", ""}, -+ {"", 3, 0, false, 0, 25, 6293656, 0, "", ""}, -+ {"", 3, 0, false, 0, 26, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 27, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 28, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 29, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 30, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 31, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 32, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 33, 0, 0, "", ""}, -+ {"init.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"initfini.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"call_gmon_start", 2, 0, false, 0, 13, 4195340, 0, "", ""}, -+ {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"__CTOR_LIST__", 1, 0, false, 0, 18, 6293128, 0, "", ""}, -+ {"__DTOR_LIST__", 1, 0, false, 0, 19, 6293144, 0, "", ""}, -+ {"__JCR_LIST__", 1, 0, false, 0, 20, 6293160, 0, "", ""}, -+ {"__do_global_dtors_aux", 2, 0, false, 0, 13, 4195376, 0, "", ""}, -+ {"completed.6183", 1, 0, false, 0, 25, 6293656, 1, "", ""}, -+ {"p.6181", 1, 0, false, 0, 24, 6293648, 0, "", ""}, -+ {"frame_dummy", 2, 0, false, 0, 13, 4195440, 0, "", ""}, -+ {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"__CTOR_END__", 1, 0, false, 0, 18, 6293136, 0, "", ""}, -+ {"__DTOR_END__", 1, 0, false, 0, 19, 6293152, 0, "", ""}, -+ {"__FRAME_END__", 1, 0, false, 0, 17, 4195968, 0, "", ""}, -+ {"__JCR_END__", 1, 0, false, 0, 20, 6293160, 0, "", ""}, -+ {"__do_global_ctors_aux", 2, 0, false, 0, 13, 4195680, 0, "", ""}, -+ {"initfini.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"_GLOBAL_OFFSET_TABLE_", 1, 2, false, 0, 23, 6293592, 0, "", ""}, -+ {"__init_array_end", 0, 2, false, 0, 18, 6293124, 0, "", ""}, -+ {"__init_array_start", 0, 2, false, 0, 18, 6293124, 0, "", ""}, -+ {"_DYNAMIC", 1, 2, false, 0, 21, 6293168, 0, "", ""}, -+ {"data_start", 32, 0, false, 0, 24, 6293632, 0, "", ""}, -+ {"__libc_csu_fini", 18, 0, false, 0, 13, 4195520, 2, "", ""}, -+ {"_start", 18, 0, false, 0, 13, 4195296, 0, "", ""}, -+ {"__gmon_start__", 32, 0, false, 0, 0, 0, 0, "", ""}, -+ {"_Jv_RegisterClasses", 32, 0, false, 0, 0, 0, 0, "", ""}, -+ {"puts@@GLIBC_2.2.5", 18, 0, false, 0, 0, 0, 396, "", ""}, -+ {"_fini", 18, 0, false, 0, 14, 4195732, 0, "", ""}, -+ {"__libc_start_main@@GLIBC_2.2.5", 18, 0, false, 0, 0, 0, 450, "", ""}, -+ {"_IO_stdin_used", 17, 0, false, 0, 15, 4195748, 4, "", ""}, -+ {"__data_start", 16, 0, false, 0, 24, 6293632, 0, "", ""}, -+ {"__dso_handle", 17, 2, false, 0, 24, 6293640, 0, "", ""}, -+ {"__libc_csu_init", 18, 0, false, 0, 13, 4195536, 137, "", ""}, -+ {"__bss_start", 16, 0, false, 0, 65521, 6293656, 0, "", ""}, -+ {"_end", 16, 0, false, 0, 65521, 6293664, 0, "", ""}, -+ {"_edata", 16, 0, false, 0, 65521, 6293656, 0, "", ""}, -+ {"main", 18, 0, false, 0, 13, 4195480, 27, "", ""}, -+ {"_init", 18, 0, false, 0, 11, 4195224, 0, "", ""}, - }, - }, - { -@@ -338,21 +338,21 @@ var fileTests = []fileTest{ - []ProgHeader{}, - nil, - []Symbol{ -- {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 1, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 3, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 4, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 5, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 6, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 8, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 9, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 11, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 13, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 15, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 16, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 14, 0, 0, "", ""}, -- {"main", 18, 0, VersionScopeNone, -1, 1, 0, 23, "", ""}, -- {"puts", 16, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, -+ {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 1, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 3, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 4, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 5, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 6, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 8, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 9, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 11, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 13, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 15, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 16, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 14, 0, 0, "", ""}, -+ {"main", 18, 0, false, 0, 1, 0, 23, "", ""}, -+ {"puts", 16, 0, false, 0, 0, 0, 0, "", ""}, - }, - }, - { -@@ -384,21 +384,21 @@ var fileTests = []fileTest{ - []ProgHeader{}, - nil, - []Symbol{ -- {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 1, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 3, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 4, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 5, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 6, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 8, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 9, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 11, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 13, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 15, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 16, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 14, 0, 0, "", ""}, -- {"main", 18, 0, VersionScopeNone, -1, 1, 0, 27, "", ""}, -- {"puts", 16, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, -+ {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 1, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 3, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 4, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 5, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 6, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 8, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 9, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 11, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 13, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 15, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 16, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 14, 0, 0, "", ""}, -+ {"main", 18, 0, false, 0, 1, 0, 27, "", ""}, -+ {"puts", 16, 0, false, 0, 0, 0, 0, "", ""}, - }, - }, - { -@@ -430,21 +430,21 @@ var fileTests = []fileTest{ - []ProgHeader{}, - nil, - []Symbol{ -- {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 1, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 3, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 4, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 5, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 6, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 8, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 9, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 11, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 13, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 15, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 16, 0, 0, "", ""}, -- {"", 3, 0, VersionScopeNone, -1, 14, 0, 0, "", ""}, -- {"main", 18, 0, VersionScopeNone, -1, 1, 0, 44, "", ""}, -- {"puts", 16, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, -+ {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 1, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 3, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 4, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 5, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 6, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 8, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 9, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 11, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 13, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 15, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 16, 0, 0, "", ""}, -+ {"", 3, 0, false, 0, 14, 0, 0, "", ""}, -+ {"main", 18, 0, false, 0, 1, 0, 44, "", ""}, -+ {"puts", 16, 0, false, 0, 0, 0, 0, "", ""}, - }, - }, - } -diff --git a/src/debug/elf/symbols_test.go b/src/debug/elf/symbols_test.go -index 8b6dac019b..6053d99acc 100644 ---- a/src/debug/elf/symbols_test.go -+++ b/src/debug/elf/symbols_test.go -@@ -39,6 +39,19 @@ func TestSymbols(t *testing.T) { - if !reflect.DeepEqual(ts, fs) { - t.Errorf("%s: Symbols = %v, want %v", file, fs, ts) - } -+ -+ for i, s := range fs { -+ if s.HasVersion { -+ // No hidden versions here. -+ if s.VersionIndex.IsHidden() { -+ t.Errorf("%s: symbol %d: unexpected hidden version", file, i) -+ } -+ if got, want := s.VersionIndex.Index(), uint16(s.VersionIndex); got != want { -+ t.Errorf("%s: symbol %d: VersionIndex.Index() == %d, want %d", file, i, got, want) -+ } -+ } -+ } -+ - } - for file, ts := range symbolsGolden { - do(file, ts, (*File).Symbols) -@@ -56,8 +69,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x1, - Value: 0x400200, - Size: 0x0, -@@ -66,8 +79,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x2, - Value: 0x40021C, - Size: 0x0, -@@ -76,8 +89,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x3, - Value: 0x400240, - Size: 0x0, -@@ -86,8 +99,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x4, - Value: 0x400268, - Size: 0x0, -@@ -96,8 +109,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x5, - Value: 0x400288, - Size: 0x0, -@@ -106,8 +119,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x6, - Value: 0x4002E8, - Size: 0x0, -@@ -116,8 +129,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x7, - Value: 0x400326, - Size: 0x0, -@@ -126,8 +139,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x8, - Value: 0x400330, - Size: 0x0, -@@ -136,8 +149,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x9, - Value: 0x400350, - Size: 0x0, -@@ -146,8 +159,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xA, - Value: 0x400368, - Size: 0x0, -@@ -156,8 +169,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xB, - Value: 0x400398, - Size: 0x0, -@@ -166,8 +179,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xC, - Value: 0x4003B0, - Size: 0x0, -@@ -176,8 +189,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xD, - Value: 0x4003E0, - Size: 0x0, -@@ -186,8 +199,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xE, - Value: 0x400594, - Size: 0x0, -@@ -196,8 +209,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xF, - Value: 0x4005A4, - Size: 0x0, -@@ -206,8 +219,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x10, - Value: 0x4005B8, - Size: 0x0, -@@ -216,8 +229,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x11, - Value: 0x4005E0, - Size: 0x0, -@@ -226,8 +239,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x12, - Value: 0x600688, - Size: 0x0, -@@ -236,8 +249,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x13, - Value: 0x600698, - Size: 0x0, -@@ -246,8 +259,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x14, - Value: 0x6006A8, - Size: 0x0, -@@ -256,8 +269,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x15, - Value: 0x6006B0, - Size: 0x0, -@@ -266,8 +279,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x16, - Value: 0x600850, - Size: 0x0, -@@ -276,8 +289,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x17, - Value: 0x600858, - Size: 0x0, -@@ -286,8 +299,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x18, - Value: 0x600880, - Size: 0x0, -@@ -296,8 +309,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x19, - Value: 0x600898, - Size: 0x0, -@@ -306,8 +319,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x1A, - Value: 0x0, - Size: 0x0, -@@ -316,8 +329,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x1B, - Value: 0x0, - Size: 0x0, -@@ -326,8 +339,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x1C, - Value: 0x0, - Size: 0x0, -@@ -336,8 +349,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x1D, - Value: 0x0, - Size: 0x0, -@@ -346,8 +359,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x1E, - Value: 0x0, - Size: 0x0, -@@ -356,8 +369,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x1F, - Value: 0x0, - Size: 0x0, -@@ -366,8 +379,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x20, - Value: 0x0, - Size: 0x0, -@@ -376,8 +389,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x21, - Value: 0x0, - Size: 0x0, -@@ -386,8 +399,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "init.c", - Info: 0x4, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF1, - Value: 0x0, - Size: 0x0, -@@ -396,8 +409,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "initfini.c", - Info: 0x4, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF1, - Value: 0x0, - Size: 0x0, -@@ -406,8 +419,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "call_gmon_start", - Info: 0x2, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xD, - Value: 0x40040C, - Size: 0x0, -@@ -416,8 +429,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "crtstuff.c", - Info: 0x4, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF1, - Value: 0x0, - Size: 0x0, -@@ -426,8 +439,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__CTOR_LIST__", - Info: 0x1, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x12, - Value: 0x600688, - Size: 0x0, -@@ -436,8 +449,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__DTOR_LIST__", - Info: 0x1, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x13, - Value: 0x600698, - Size: 0x0, -@@ -446,8 +459,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__JCR_LIST__", - Info: 0x1, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x14, - Value: 0x6006A8, - Size: 0x0, -@@ -456,8 +469,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__do_global_dtors_aux", - Info: 0x2, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xD, - Value: 0x400430, - Size: 0x0, -@@ -466,8 +479,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "completed.6183", - Info: 0x1, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x19, - Value: 0x600898, - Size: 0x1, -@@ -476,8 +489,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "p.6181", - Info: 0x1, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x18, - Value: 0x600890, - Size: 0x0, -@@ -486,8 +499,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "frame_dummy", - Info: 0x2, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xD, - Value: 0x400470, - Size: 0x0, -@@ -496,8 +509,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "crtstuff.c", - Info: 0x4, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF1, - Value: 0x0, - Size: 0x0, -@@ -506,8 +519,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__CTOR_END__", - Info: 0x1, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x12, - Value: 0x600690, - Size: 0x0, -@@ -516,8 +529,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__DTOR_END__", - Info: 0x1, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x13, - Value: 0x6006A0, - Size: 0x0, -@@ -526,8 +539,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__FRAME_END__", - Info: 0x1, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x11, - Value: 0x400680, - Size: 0x0, -@@ -536,8 +549,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__JCR_END__", - Info: 0x1, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x14, - Value: 0x6006A8, - Size: 0x0, -@@ -546,8 +559,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__do_global_ctors_aux", - Info: 0x2, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xD, - Value: 0x400560, - Size: 0x0, -@@ -556,8 +569,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "initfini.c", - Info: 0x4, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF1, - Value: 0x0, - Size: 0x0, -@@ -566,8 +579,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "hello.c", - Info: 0x4, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF1, - Value: 0x0, - Size: 0x0, -@@ -576,8 +589,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "_GLOBAL_OFFSET_TABLE_", - Info: 0x1, - Other: 0x2, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x17, - Value: 0x600858, - Size: 0x0, -@@ -586,8 +599,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__init_array_end", - Info: 0x0, - Other: 0x2, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x12, - Value: 0x600684, - Size: 0x0, -@@ -596,8 +609,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__init_array_start", - Info: 0x0, - Other: 0x2, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x12, - Value: 0x600684, - Size: 0x0, -@@ -606,8 +619,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "_DYNAMIC", - Info: 0x1, - Other: 0x2, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x15, - Value: 0x6006B0, - Size: 0x0, -@@ -616,8 +629,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "data_start", - Info: 0x20, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x18, - Value: 0x600880, - Size: 0x0, -@@ -626,8 +639,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__libc_csu_fini", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xD, - Value: 0x4004C0, - Size: 0x2, -@@ -636,8 +649,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "_start", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xD, - Value: 0x4003E0, - Size: 0x0, -@@ -646,8 +659,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__gmon_start__", - Info: 0x20, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x0, - Value: 0x0, - Size: 0x0, -@@ -656,8 +669,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "_Jv_RegisterClasses", - Info: 0x20, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x0, - Value: 0x0, - Size: 0x0, -@@ -666,8 +679,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "puts@@GLIBC_2.2.5", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x0, - Value: 0x0, - Size: 0x18C, -@@ -676,8 +689,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "_fini", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xE, - Value: 0x400594, - Size: 0x0, -@@ -686,8 +699,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__libc_start_main@@GLIBC_2.2.5", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x0, - Value: 0x0, - Size: 0x1C2, -@@ -696,8 +709,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "_IO_stdin_used", - Info: 0x11, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xF, - Value: 0x4005A4, - Size: 0x4, -@@ -706,8 +719,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__data_start", - Info: 0x10, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x18, - Value: 0x600880, - Size: 0x0, -@@ -716,8 +729,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__dso_handle", - Info: 0x11, - Other: 0x2, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x18, - Value: 0x600888, - Size: 0x0, -@@ -726,8 +739,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__libc_csu_init", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xD, - Value: 0x4004D0, - Size: 0x89, -@@ -736,8 +749,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "__bss_start", - Info: 0x10, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF1, - Value: 0x600898, - Size: 0x0, -@@ -746,8 +759,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "_end", - Info: 0x10, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF1, - Value: 0x6008A0, - Size: 0x0, -@@ -756,8 +769,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "_edata", - Info: 0x10, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF1, - Value: 0x600898, - Size: 0x0, -@@ -766,8 +779,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "main", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xD, - Value: 0x400498, - Size: 0x1B, -@@ -776,8 +789,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "_init", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xB, - Value: 0x400398, - Size: 0x0, -@@ -788,8 +801,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "go-relocation-test-clang.c", - Info: 0x4, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF1, - Value: 0x0, - Size: 0x0, -@@ -798,8 +811,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: ".Linfo_string0", - Info: 0x0, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xC, - Value: 0x0, - Size: 0x0, -@@ -808,8 +821,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: ".Linfo_string1", - Info: 0x0, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xC, - Value: 0x2C, - Size: 0x0, -@@ -818,8 +831,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: ".Linfo_string2", - Info: 0x0, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xC, - Value: 0x47, - Size: 0x0, -@@ -828,8 +841,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: ".Linfo_string3", - Info: 0x0, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xC, - Value: 0x4C, - Size: 0x0, -@@ -838,8 +851,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: ".Linfo_string4", - Info: 0x0, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xC, - Value: 0x4E, - Size: 0x0, -@@ -848,8 +861,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x1, - Value: 0x0, - Size: 0x0, -@@ -858,8 +871,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x2, - Value: 0x0, - Size: 0x0, -@@ -868,8 +881,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x3, - Value: 0x0, - Size: 0x0, -@@ -878,8 +891,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x4, - Value: 0x0, - Size: 0x0, -@@ -888,8 +901,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x6, - Value: 0x0, - Size: 0x0, -@@ -898,8 +911,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x7, - Value: 0x0, - Size: 0x0, -@@ -908,8 +921,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x8, - Value: 0x0, - Size: 0x0, -@@ -918,8 +931,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xA, - Value: 0x0, - Size: 0x0, -@@ -928,8 +941,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xC, - Value: 0x0, - Size: 0x0, -@@ -938,8 +951,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xD, - Value: 0x0, - Size: 0x0, -@@ -948,8 +961,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xE, - Value: 0x0, - Size: 0x0, -@@ -958,8 +971,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xF, - Value: 0x0, - Size: 0x0, -@@ -968,8 +981,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "", - Info: 0x3, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0x10, - Value: 0x0, - Size: 0x0, -@@ -978,8 +991,8 @@ var symbolsGolden = map[string][]Symbol{ - Name: "v", - Info: 0x11, - Other: 0x0, -- VersionScope: VersionScopeNone, -- VersionIndex: -1, -+ HasVersion: false, -+ VersionIndex: 0, - Section: 0xFFF2, - Value: 0x4, - Size: 0x4, -@@ -994,7 +1007,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "__gmon_start__", - Info: 0x20, - Other: 0x0, -- VersionScope: VersionScopeLocal, -+ HasVersion: true, - VersionIndex: 0x0, - Section: 0x0, - Value: 0x0, -@@ -1004,7 +1017,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "puts", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x2, - Section: 0x0, - Value: 0x0, -@@ -1016,7 +1029,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "__libc_start_main", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x2, - Section: 0x0, - Value: 0x0, -@@ -1032,7 +1045,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZNSo3putEc", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1044,7 +1057,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "strchr", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x4, - Section: 0x0, - Value: 0x0, -@@ -1056,7 +1069,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "__cxa_finalize", - Info: 0x22, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x4, - Section: 0x0, - Value: 0x0, -@@ -1068,7 +1081,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZNSo5tellpEv", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1080,7 +1093,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZNSo5seekpElSt12_Ios_Seekdir", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1092,7 +1105,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_Znwm", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1104,7 +1117,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZdlPvm", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x5, - Section: 0x0, - Value: 0x0, -@@ -1116,7 +1129,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "__stack_chk_fail", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x6, - Section: 0x0, - Value: 0x0, -@@ -1128,7 +1141,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x7, - Section: 0x0, - Value: 0x0, -@@ -1140,7 +1153,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZNSo5seekpESt4fposI11__mbstate_tE", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1152,7 +1165,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZNSi4readEPcl", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1164,7 +1177,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZNSi5seekgESt4fposI11__mbstate_tE", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1176,7 +1189,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZNSo5writeEPKcl", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1188,7 +1201,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZNSi5seekgElSt12_Ios_Seekdir", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1200,7 +1213,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZSt21ios_base_library_initv", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x8, - Section: 0x0, - Value: 0x0, -@@ -1212,7 +1225,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "TIFFClientOpen", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x9, - Section: 0x0, - Value: 0x0, -@@ -1224,7 +1237,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZNSt9basic_iosIcSt11char_traitsIcEE5clearESt12_Ios_Iostate", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1236,7 +1249,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ZNSi5tellgEv", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x3, - Section: 0x0, - Value: 0x0, -@@ -1248,7 +1261,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ITM_deregisterTMCloneTable", - Info: 0x20, - Other: 0x0, -- VersionScope: VersionScopeGlobal, -+ HasVersion: true, - VersionIndex: 0x1, - Section: 0x0, - Value: 0x0, -@@ -1258,7 +1271,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "__gmon_start__", - Info: 0x20, - Other: 0x0, -- VersionScope: VersionScopeGlobal, -+ HasVersion: true, - VersionIndex: 0x1, - Section: 0x0, - Value: 0x0, -@@ -1268,7 +1281,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_ITM_registerTMCloneTable", - Info: 0x20, - Other: 0x0, -- VersionScope: VersionScopeGlobal, -+ HasVersion: true, - VersionIndex: 0x1, - Section: 0x0, - Value: 0x0, -@@ -1278,7 +1291,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "LIBTIFFXX_4.0", - Info: 0x11, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x2, - Section: 0xFFF1, - Value: 0x0, -@@ -1290,7 +1303,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_Z14TIFFStreamOpenPKcPSo", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x2, - Section: 0xF, - Value: 0x1860, -@@ -1302,7 +1315,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ - Name: "_Z14TIFFStreamOpenPKcPSi", - Info: 0x12, - Other: 0x0, -- VersionScope: VersionScopeSpecific, -+ HasVersion: true, - VersionIndex: 0x2, - Section: 0xF, - Value: 0x1920, -diff --git a/src/encoding/binary/binary.go b/src/encoding/binary/binary.go -index d80aa8e11a..c92dfded27 100644 ---- a/src/encoding/binary/binary.go -+++ b/src/encoding/binary/binary.go -@@ -65,17 +65,20 @@ var BigEndian bigEndian - - type littleEndian struct{} - -+// Uint16 returns the uint16 representation of b[0:2]. - func (littleEndian) Uint16(b []byte) uint16 { - _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 - return uint16(b[0]) | uint16(b[1])<<8 - } - -+// PutUint16 stores v into b[0:2]. - func (littleEndian) PutUint16(b []byte, v uint16) { - _ = b[1] // early bounds check to guarantee safety of writes below - b[0] = byte(v) - b[1] = byte(v >> 8) - } - -+// AppendUint16 appends the bytes of v to b and returns the appended slice. - func (littleEndian) AppendUint16(b []byte, v uint16) []byte { - return append(b, - byte(v), -@@ -83,11 +86,13 @@ func (littleEndian) AppendUint16(b []byte, v uint16) []byte { - ) - } - -+// Uint32 returns the uint32 representation of b[0:4]. - func (littleEndian) Uint32(b []byte) uint32 { - _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 - return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 - } - -+// PutUint32 stores v into b[0:4]. - func (littleEndian) PutUint32(b []byte, v uint32) { - _ = b[3] // early bounds check to guarantee safety of writes below - b[0] = byte(v) -@@ -96,6 +101,7 @@ func (littleEndian) PutUint32(b []byte, v uint32) { - b[3] = byte(v >> 24) - } - -+// AppendUint32 appends the bytes of v to b and returns the appended slice. - func (littleEndian) AppendUint32(b []byte, v uint32) []byte { - return append(b, - byte(v), -@@ -105,12 +111,14 @@ func (littleEndian) AppendUint32(b []byte, v uint32) []byte { - ) - } - -+// Uint64 returns the uint64 representation of b[0:8]. - func (littleEndian) Uint64(b []byte) uint64 { - _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | - uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 - } - -+// PutUint64 stores v into b[0:8]. - func (littleEndian) PutUint64(b []byte, v uint64) { - _ = b[7] // early bounds check to guarantee safety of writes below - b[0] = byte(v) -@@ -123,6 +131,7 @@ func (littleEndian) PutUint64(b []byte, v uint64) { - b[7] = byte(v >> 56) - } - -+// AppendUint64 appends the bytes of v to b and returns the appended slice. - func (littleEndian) AppendUint64(b []byte, v uint64) []byte { - return append(b, - byte(v), -@@ -142,17 +151,20 @@ func (littleEndian) GoString() string { return "binary.LittleEndian" } - - type bigEndian struct{} - -+// Uint16 returns the uint16 representation of b[0:2]. - func (bigEndian) Uint16(b []byte) uint16 { - _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 - return uint16(b[1]) | uint16(b[0])<<8 - } - -+// PutUint16 stores v into b[0:2]. - func (bigEndian) PutUint16(b []byte, v uint16) { - _ = b[1] // early bounds check to guarantee safety of writes below - b[0] = byte(v >> 8) - b[1] = byte(v) - } - -+// AppendUint16 appends the bytes of v to b and returns the appended slice. - func (bigEndian) AppendUint16(b []byte, v uint16) []byte { - return append(b, - byte(v>>8), -@@ -160,11 +172,13 @@ func (bigEndian) AppendUint16(b []byte, v uint16) []byte { - ) - } - -+// Uint32 returns the uint32 representation of b[0:4]. - func (bigEndian) Uint32(b []byte) uint32 { - _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 - return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24 - } - -+// PutUint32 stores v into b[0:4]. - func (bigEndian) PutUint32(b []byte, v uint32) { - _ = b[3] // early bounds check to guarantee safety of writes below - b[0] = byte(v >> 24) -@@ -173,6 +187,7 @@ func (bigEndian) PutUint32(b []byte, v uint32) { - b[3] = byte(v) - } - -+// AppendUint32 appends the bytes of v to b and returns the appended slice. - func (bigEndian) AppendUint32(b []byte, v uint32) []byte { - return append(b, - byte(v>>24), -@@ -182,12 +197,14 @@ func (bigEndian) AppendUint32(b []byte, v uint32) []byte { - ) - } - -+// Uint64 returns the uint64 representation of b[0:8]. - func (bigEndian) Uint64(b []byte) uint64 { - _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | - uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 - } - -+// PutUint64 stores v into b[0:8]. - func (bigEndian) PutUint64(b []byte, v uint64) { - _ = b[7] // early bounds check to guarantee safety of writes below - b[0] = byte(v >> 56) -@@ -200,6 +217,7 @@ func (bigEndian) PutUint64(b []byte, v uint64) { - b[7] = byte(v) - } - -+// AppendUint64 appends the bytes of v to b and returns the appended slice. - func (bigEndian) AppendUint64(b []byte, v uint64) []byte { - return append(b, - byte(v>>56), -diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go -index 98102291ab..3b398c9fc3 100644 ---- a/src/encoding/json/decode.go -+++ b/src/encoding/json/decode.go -@@ -113,9 +113,6 @@ func Unmarshal(data []byte, v any) error { - // The input can be assumed to be a valid encoding of - // a JSON value. UnmarshalJSON must copy the JSON data - // if it wishes to retain the data after returning. --// --// By convention, to approximate the behavior of [Unmarshal] itself, --// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op. - type Unmarshaler interface { - UnmarshalJSON([]byte) error - } -diff --git a/src/encoding/json/decode_test.go b/src/encoding/json/decode_test.go -index de09fae50f..a2b462af77 100644 ---- a/src/encoding/json/decode_test.go -+++ b/src/encoding/json/decode_test.go -@@ -1797,19 +1797,12 @@ func TestNullString(t *testing.T) { - } - } - --func intp(x int) *int { -- p := new(int) -- *p = x -- return p --} -- --func intpp(x *int) **int { -- pp := new(*int) -- *pp = x -- return pp -+func addr[T any](v T) *T { -+ return &v - } - - func TestInterfaceSet(t *testing.T) { -+ errUnmarshal := &UnmarshalTypeError{Value: "object", Offset: 6, Type: reflect.TypeFor[int](), Field: "X"} - tests := []struct { - CaseName - pre any -@@ -1820,21 +1813,55 @@ func TestInterfaceSet(t *testing.T) { - {Name(""), "foo", `2`, 2.0}, - {Name(""), "foo", `true`, true}, - {Name(""), "foo", `null`, nil}, -- -- {Name(""), nil, `null`, nil}, -- {Name(""), new(int), `null`, nil}, -- {Name(""), (*int)(nil), `null`, nil}, -- {Name(""), new(*int), `null`, new(*int)}, -- {Name(""), (**int)(nil), `null`, nil}, -- {Name(""), intp(1), `null`, nil}, -- {Name(""), intpp(nil), `null`, intpp(nil)}, -- {Name(""), intpp(intp(1)), `null`, intpp(nil)}, -+ {Name(""), map[string]any{}, `true`, true}, -+ {Name(""), []string{}, `true`, true}, -+ -+ {Name(""), any(nil), `null`, any(nil)}, -+ {Name(""), (*int)(nil), `null`, any(nil)}, -+ {Name(""), (*int)(addr(0)), `null`, any(nil)}, -+ {Name(""), (*int)(addr(1)), `null`, any(nil)}, -+ {Name(""), (**int)(nil), `null`, any(nil)}, -+ {Name(""), (**int)(addr[*int](nil)), `null`, (**int)(addr[*int](nil))}, -+ {Name(""), (**int)(addr(addr(1))), `null`, (**int)(addr[*int](nil))}, -+ {Name(""), (***int)(nil), `null`, any(nil)}, -+ {Name(""), (***int)(addr[**int](nil)), `null`, (***int)(addr[**int](nil))}, -+ {Name(""), (***int)(addr(addr[*int](nil))), `null`, (***int)(addr[**int](nil))}, -+ {Name(""), (***int)(addr(addr(addr(1)))), `null`, (***int)(addr[**int](nil))}, -+ -+ {Name(""), any(nil), `2`, float64(2)}, -+ {Name(""), (int)(1), `2`, float64(2)}, -+ {Name(""), (*int)(nil), `2`, float64(2)}, -+ {Name(""), (*int)(addr(0)), `2`, (*int)(addr(2))}, -+ {Name(""), (*int)(addr(1)), `2`, (*int)(addr(2))}, -+ {Name(""), (**int)(nil), `2`, float64(2)}, -+ {Name(""), (**int)(addr[*int](nil)), `2`, (**int)(addr(addr(2)))}, -+ {Name(""), (**int)(addr(addr(1))), `2`, (**int)(addr(addr(2)))}, -+ {Name(""), (***int)(nil), `2`, float64(2)}, -+ {Name(""), (***int)(addr[**int](nil)), `2`, (***int)(addr(addr(addr(2))))}, -+ {Name(""), (***int)(addr(addr[*int](nil))), `2`, (***int)(addr(addr(addr(2))))}, -+ {Name(""), (***int)(addr(addr(addr(1)))), `2`, (***int)(addr(addr(addr(2))))}, -+ -+ {Name(""), any(nil), `{}`, map[string]any{}}, -+ {Name(""), (int)(1), `{}`, map[string]any{}}, -+ {Name(""), (*int)(nil), `{}`, map[string]any{}}, -+ {Name(""), (*int)(addr(0)), `{}`, errUnmarshal}, -+ {Name(""), (*int)(addr(1)), `{}`, errUnmarshal}, -+ {Name(""), (**int)(nil), `{}`, map[string]any{}}, -+ {Name(""), (**int)(addr[*int](nil)), `{}`, errUnmarshal}, -+ {Name(""), (**int)(addr(addr(1))), `{}`, errUnmarshal}, -+ {Name(""), (***int)(nil), `{}`, map[string]any{}}, -+ {Name(""), (***int)(addr[**int](nil)), `{}`, errUnmarshal}, -+ {Name(""), (***int)(addr(addr[*int](nil))), `{}`, errUnmarshal}, -+ {Name(""), (***int)(addr(addr(addr(1)))), `{}`, errUnmarshal}, - } - for _, tt := range tests { - t.Run(tt.Name, func(t *testing.T) { - b := struct{ X any }{tt.pre} - blob := `{"X":` + tt.json + `}` - if err := Unmarshal([]byte(blob), &b); err != nil { -+ if wantErr, _ := tt.post.(error); equalError(err, wantErr) { -+ return -+ } - t.Fatalf("%s: Unmarshal(%#q) error: %v", tt.Where, blob, err) - } - if !reflect.DeepEqual(b.X, tt.post) { -diff --git a/src/fmt/doc.go b/src/fmt/doc.go -index b90db7bedc..fa0ffa7f00 100644 ---- a/src/fmt/doc.go -+++ b/src/fmt/doc.go -@@ -50,6 +50,9 @@ Floating-point and complex constituents: - %x hexadecimal notation (with decimal power of two exponent), e.g. -0x1.23abcp+20 - %X upper-case hexadecimal notation, e.g. -0X1.23ABCP+20 - -+ The exponent is always a decimal integer. -+ For formats other than %b the exponent is at least two digits. -+ - String and slice of bytes (treated equivalently with these verbs): - - %s the uninterpreted bytes of the string or slice -diff --git a/src/fmt/fmt_test.go b/src/fmt/fmt_test.go -index b7f9ccd494..82daf62771 100644 ---- a/src/fmt/fmt_test.go -+++ b/src/fmt/fmt_test.go -@@ -11,7 +11,6 @@ import ( - "io" - "math" - "reflect" -- "runtime" - "strings" - "testing" - "time" -@@ -112,6 +111,19 @@ func (p *P) String() string { - return "String(p)" - } - -+// Fn is a function type with a String method. -+type Fn func() int -+ -+func (fn Fn) String() string { return "String(fn)" } -+ -+var fnValue Fn -+ -+// U is a type with two unexported function fields. -+type U struct { -+ u func() string -+ fn Fn -+} -+ - var barray = [5]renamedUint8{1, 2, 3, 4, 5} - var bslice = barray[:] - -@@ -714,7 +726,6 @@ var fmtTests = []struct { - // go syntax - {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`}, - {"%#v", new(byte), "(*uint8)(0xPTR)"}, -- {"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"}, - {"%#v", make(chan int), "(chan int)(0xPTR)"}, - {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"}, - {"%#v", 1000000000, "1000000000"}, -@@ -737,6 +748,54 @@ var fmtTests = []struct { - {"%#v", 1.2345678, "1.2345678"}, - {"%#v", float32(1.2345678), "1.2345678"}, - -+ // functions -+ {"%v", TestFmtInterface, "0xPTR"}, // simple function -+ {"%v", reflect.ValueOf(TestFmtInterface), "0xPTR"}, -+ {"%v", G.GoString, "0xPTR"}, // method expression -+ {"%v", reflect.ValueOf(G.GoString), "0xPTR"}, -+ {"%v", G(23).GoString, "0xPTR"}, // method value -+ {"%v", reflect.ValueOf(G(23).GoString), "0xPTR"}, -+ {"%v", reflect.ValueOf(G(23)).Method(0), "0xPTR"}, -+ {"%v", Fn.String, "0xPTR"}, // method of function type -+ {"%v", reflect.ValueOf(Fn.String), "0xPTR"}, -+ {"%v", fnValue, "String(fn)"}, // variable of function type with String method -+ {"%v", reflect.ValueOf(fnValue), "String(fn)"}, -+ {"%v", [1]Fn{fnValue}, "[String(fn)]"}, // array of function type with String method -+ {"%v", reflect.ValueOf([1]Fn{fnValue}), "[String(fn)]"}, -+ {"%v", fnValue.String, "0xPTR"}, // method value from function type -+ {"%v", reflect.ValueOf(fnValue.String), "0xPTR"}, -+ {"%v", reflect.ValueOf(fnValue).Method(0), "0xPTR"}, -+ {"%v", U{}.u, " "}, // unexported function field -+ {"%v", reflect.ValueOf(U{}.u), " "}, -+ {"%v", reflect.ValueOf(U{}).Field(0), " "}, -+ {"%v", U{fn: fnValue}.fn, "String(fn)"}, // unexported field of function type with String method -+ {"%v", reflect.ValueOf(U{fn: fnValue}.fn), "String(fn)"}, -+ {"%v", reflect.ValueOf(U{fn: fnValue}).Field(1), " "}, -+ -+ // functions with go syntax -+ {"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"}, // simple function -+ {"%#v", reflect.ValueOf(TestFmtInterface), "(func(*testing.T))(0xPTR)"}, -+ {"%#v", G.GoString, "(func(fmt_test.G) string)(0xPTR)"}, // method expression -+ {"%#v", reflect.ValueOf(G.GoString), "(func(fmt_test.G) string)(0xPTR)"}, -+ {"%#v", G(23).GoString, "(func() string)(0xPTR)"}, // method value -+ {"%#v", reflect.ValueOf(G(23).GoString), "(func() string)(0xPTR)"}, -+ {"%#v", reflect.ValueOf(G(23)).Method(0), "(func() string)(0xPTR)"}, -+ {"%#v", Fn.String, "(func(fmt_test.Fn) string)(0xPTR)"}, // method of function type -+ {"%#v", reflect.ValueOf(Fn.String), "(func(fmt_test.Fn) string)(0xPTR)"}, -+ {"%#v", fnValue, "(fmt_test.Fn)(nil)"}, // variable of function type with String method -+ {"%#v", reflect.ValueOf(fnValue), "(fmt_test.Fn)(nil)"}, -+ {"%#v", [1]Fn{fnValue}, "[1]fmt_test.Fn{(fmt_test.Fn)(nil)}"}, // array of function type with String method -+ {"%#v", reflect.ValueOf([1]Fn{fnValue}), "[1]fmt_test.Fn{(fmt_test.Fn)(nil)}"}, -+ {"%#v", fnValue.String, "(func() string)(0xPTR)"}, // method value from function type -+ {"%#v", reflect.ValueOf(fnValue.String), "(func() string)(0xPTR)"}, -+ {"%#v", reflect.ValueOf(fnValue).Method(0), "(func() string)(0xPTR)"}, -+ {"%#v", U{}.u, "(func() string)(nil)"}, // unexported function field -+ {"%#v", reflect.ValueOf(U{}.u), "(func() string)(nil)"}, -+ {"%#v", reflect.ValueOf(U{}).Field(0), "(func() string)(nil)"}, -+ {"%#v", U{fn: fnValue}.fn, "(fmt_test.Fn)(nil)"}, // unexported field of function type with String method -+ {"%#v", reflect.ValueOf(U{fn: fnValue}.fn), "(fmt_test.Fn)(nil)"}, -+ {"%#v", reflect.ValueOf(U{fn: fnValue}).Field(1), "(fmt_test.Fn)(nil)"}, -+ - // Whole number floats are printed without decimals. See Issue 27634. - {"%#v", 1.0, "1"}, - {"%#v", 1000000.0, "1e+06"}, -@@ -1438,6 +1497,9 @@ var mallocTest = []struct { - {0, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }}, - {0, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x", 7) }}, - {0, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x", 1<<16) }}, -+ {1, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); i := 1 << 16; Fprintf(&mallocBuf, "%x", i) }}, // not constant -+ {4, `Fprintf(buf, "%v")`, func() { mallocBuf.Reset(); s := []int{1, 2}; Fprintf(&mallocBuf, "%v", s) }}, -+ {1, `Fprintf(buf, "%v")`, func() { mallocBuf.Reset(); type P struct{ x, y int }; Fprintf(&mallocBuf, "%v", P{1, 2}) }}, - {2, `Fprintf(buf, "%80000s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%80000s", "hello") }}, // large buffer (>64KB) - // If the interface value doesn't need to allocate, amortized allocation overhead should be zero. - {0, `Fprintf(buf, "%x %x %x")`, func() { -@@ -1452,8 +1514,6 @@ func TestCountMallocs(t *testing.T) { - switch { - case testing.Short(): - t.Skip("skipping malloc count in short mode") -- case runtime.GOMAXPROCS(0) > 1: -- t.Skip("skipping; GOMAXPROCS>1") - case race.Enabled: - t.Skip("skipping malloc count under race detector") - } -diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index cc7f4df7f3..a62a5173b9 100644 ---- a/src/go/build/deps_test.go -+++ b/src/go/build/deps_test.go -@@ -444,6 +444,10 @@ var depsRules = ` - NET, log - < net/mail; - -+ # FIPS is the FIPS 140 module. -+ # It must not depend on external crypto packages. -+ # See also fips140deps.AllowedInternalPackages. -+ - io, math/rand/v2 < crypto/internal/randutil; - - STR < crypto/internal/impl; -@@ -455,8 +459,6 @@ var depsRules = ` - internal/cpu, internal/goarch < crypto/internal/fips140deps/cpu; - internal/godebug < crypto/internal/fips140deps/godebug; - -- # FIPS is the FIPS 140 module. -- # It must not depend on external crypto packages. - STR, crypto/internal/impl, - crypto/internal/entropy, - crypto/internal/randutil, -@@ -491,63 +493,49 @@ var depsRules = ` - < crypto/internal/fips140/rsa - < FIPS; - -- FIPS < crypto/internal/fips140/check/checktest; -+ FIPS, internal/godebug < crypto/fips140; - -- FIPS, sync/atomic < crypto/tls/internal/fips140tls; -+ crypto, hash !< FIPS; - -- FIPS, internal/godebug, hash < crypto/fips140, crypto/internal/fips140only; -+ # CRYPTO is core crypto algorithms - no cgo, fmt, net. -+ # Mostly wrappers around the FIPS module. - - NONE < crypto/internal/boring/sig, crypto/internal/boring/syso; -- sync/atomic < crypto/internal/boring/bcache, crypto/internal/boring/fips140tls; -- crypto/internal/boring/sig, crypto/tls/internal/fips140tls < crypto/tls/fipsonly; -+ sync/atomic < crypto/internal/boring/bcache; - -- # CRYPTO is core crypto algorithms - no cgo, fmt, net. -- FIPS, crypto/internal/fips140only, -+ FIPS, internal/godebug, hash, embed, - crypto/internal/boring/sig, - crypto/internal/boring/syso, -- golang.org/x/sys/cpu, -- hash, embed -+ crypto/internal/boring/bcache -+ < crypto/internal/fips140only - < crypto - < crypto/subtle - < crypto/cipher -- < crypto/sha3; -- -- crypto/cipher, -- crypto/internal/boring/bcache - < crypto/internal/boring -- < crypto/boring; -- -- crypto/boring -- < crypto/aes, crypto/des, crypto/hmac, crypto/md5, crypto/rc4, -- crypto/sha1, crypto/sha256, crypto/sha512, crypto/hkdf; -- -- crypto/boring, crypto/internal/fips140/edwards25519/field -- < crypto/ecdh; -- -- crypto/hmac < crypto/pbkdf2; -- -- crypto/internal/fips140/mlkem < crypto/mlkem; -- -- crypto/aes, -- crypto/des, -- crypto/ecdh, -- crypto/hmac, -- crypto/md5, -- crypto/rc4, -- crypto/sha1, -- crypto/sha256, -- crypto/sha512, -- crypto/sha3, -- crypto/hkdf -+ < crypto/boring -+ < crypto/aes, -+ crypto/des, -+ crypto/rc4, -+ crypto/md5, -+ crypto/sha1, -+ crypto/sha256, -+ crypto/sha512, -+ crypto/sha3, -+ crypto/hmac, -+ crypto/hkdf, -+ crypto/pbkdf2, -+ crypto/ecdh, -+ crypto/mlkem - < CRYPTO; - - CGO, fmt, net !< CRYPTO; - -- # CRYPTO-MATH is core bignum-based crypto - no cgo, net; fmt now ok. -+ # CRYPTO-MATH is crypto that exposes math/big APIs - no cgo, net; fmt now ok. -+ - CRYPTO, FMT, math/big - < crypto/internal/boring/bbig - < crypto/rand -- < crypto/ed25519 -+ < crypto/ed25519 # depends on crypto/rand.Reader - < encoding/asn1 - < golang.org/x/crypto/cryptobyte/asn1 - < golang.org/x/crypto/cryptobyte -@@ -558,23 +546,29 @@ var depsRules = ` - CGO, net !< CRYPTO-MATH; - - # TLS, Prince of Dependencies. -- CRYPTO-MATH, NET, container/list, encoding/hex, encoding/pem -+ -+ FIPS, sync/atomic < crypto/tls/internal/fips140tls; -+ -+ crypto/internal/boring/sig, crypto/tls/internal/fips140tls < crypto/tls/fipsonly; -+ -+ CRYPTO, golang.org/x/sys/cpu, encoding/binary, reflect - < golang.org/x/crypto/internal/alias - < golang.org/x/crypto/internal/subtle - < golang.org/x/crypto/chacha20 - < golang.org/x/crypto/internal/poly1305 -- < golang.org/x/crypto/chacha20poly1305 -+ < golang.org/x/crypto/chacha20poly1305; -+ -+ CRYPTO-MATH, NET, container/list, encoding/hex, encoding/pem, -+ golang.org/x/crypto/chacha20poly1305, crypto/tls/internal/fips140tls - < crypto/internal/hpke - < crypto/x509/internal/macos -- < crypto/x509/pkix; -- -- crypto/tls/internal/fips140tls, crypto/x509/pkix -+ < crypto/x509/pkix - < crypto/x509 - < crypto/tls; - - # crypto-aware packages - -- DEBUG, go/build, go/types, text/scanner, crypto/md5 -+ DEBUG, go/build, go/types, text/scanner, crypto/sha256 - < internal/pkgbits, internal/exportdata - < go/internal/gcimporter, go/internal/gccgoimporter, go/internal/srcimporter - < go/importer; -@@ -666,7 +660,7 @@ var depsRules = ` - < testing/slogtest; - - FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, -- internal/godebug, math/rand, encoding/hex, crypto/sha256 -+ internal/godebug, math/rand, encoding/hex - < internal/fuzz; - - OS, flag, testing, internal/cfg, internal/platform, internal/goroot -@@ -696,6 +690,9 @@ var depsRules = ` - CGO, FMT - < crypto/internal/sysrand/internal/seccomp; - -+ FIPS -+ < crypto/internal/fips140/check/checktest; -+ - # v2 execution trace parser. - FMT - < internal/trace/event; -diff --git a/src/go/doc/example.go b/src/go/doc/example.go -index 0618f2bd9b..7a8c26291d 100644 ---- a/src/go/doc/example.go -+++ b/src/go/doc/example.go -@@ -192,13 +192,6 @@ func playExample(file *ast.File, f *ast.FuncDecl) *ast.File { - // Find unresolved identifiers and uses of top-level declarations. - depDecls, unresolved := findDeclsAndUnresolved(body, topDecls, typMethods) - -- // Remove predeclared identifiers from unresolved list. -- for n := range unresolved { -- if predeclaredTypes[n] || predeclaredConstants[n] || predeclaredFuncs[n] { -- delete(unresolved, n) -- } -- } -- - // Use unresolved identifiers to determine the imports used by this - // example. The heuristic assumes package names match base import - // paths for imports w/o renames (should be good enough most of the time). -@@ -251,6 +244,13 @@ func playExample(file *ast.File, f *ast.FuncDecl) *ast.File { - } - } - -+ // Remove predeclared identifiers from unresolved list. -+ for n := range unresolved { -+ if predeclaredTypes[n] || predeclaredConstants[n] || predeclaredFuncs[n] { -+ delete(unresolved, n) -+ } -+ } -+ - // If there are other unresolved identifiers, give up because this - // synthesized file is not going to build. - if len(unresolved) > 0 { -diff --git a/src/go/doc/testdata/examples/shadow_predeclared.go b/src/go/doc/testdata/examples/shadow_predeclared.go -new file mode 100644 -index 0000000000..7e9f30d9b4 ---- /dev/null -+++ b/src/go/doc/testdata/examples/shadow_predeclared.go -@@ -0,0 +1,19 @@ -+// Copyright 2021 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package foo_test -+ -+import ( -+ "fmt" -+ -+ "example.com/error" -+) -+ -+func Print(s string) { -+ fmt.Println(s) -+} -+ -+func Example() { -+ Print(error.Hello) -+} -diff --git a/src/go/doc/testdata/examples/shadow_predeclared.golden b/src/go/doc/testdata/examples/shadow_predeclared.golden -new file mode 100644 -index 0000000000..65598bed62 ---- /dev/null -+++ b/src/go/doc/testdata/examples/shadow_predeclared.golden -@@ -0,0 +1,16 @@ -+-- .Play -- -+package main -+ -+import ( -+ "fmt" -+ -+ "example.com/error" -+) -+ -+func Print(s string) { -+ fmt.Println(s) -+} -+ -+func main() { -+ Print(error.Hello) -+} -diff --git a/src/go/types/api.go b/src/go/types/api.go -index dea974bec8..beb2258c8b 100644 ---- a/src/go/types/api.go -+++ b/src/go/types/api.go -@@ -217,11 +217,19 @@ type Info struct { - // - // The Types map does not record the type of every identifier, - // only those that appear where an arbitrary expression is -- // permitted. For instance, the identifier f in a selector -- // expression x.f is found only in the Selections map, the -- // identifier z in a variable declaration 'var z int' is found -- // only in the Defs map, and identifiers denoting packages in -- // qualified identifiers are collected in the Uses map. -+ // permitted. For instance: -+ // - an identifier f in a selector expression x.f is found -+ // only in the Selections map; -+ // - an identifier z in a variable declaration 'var z int' -+ // is found only in the Defs map; -+ // - an identifier p denoting a package in a qualified -+ // identifier p.X is found only in the Uses map. -+ // -+ // Similarly, no type is recorded for the (synthetic) FuncType -+ // node in a FuncDecl.Type field, since there is no corresponding -+ // syntactic function type expression in the source in this case -+ // Instead, the function type is found in the Defs.map entry for -+ // the corresponding function declaration. - Types map[ast.Expr]TypeAndValue - - // Instances maps identifiers denoting generic types or functions to their -diff --git a/src/go/types/signature.go b/src/go/types/signature.go -index 681eb85fd7..ff405318ee 100644 ---- a/src/go/types/signature.go -+++ b/src/go/types/signature.go -@@ -195,7 +195,7 @@ func (check *Checker) collectRecv(rparam *ast.Field, scopePos token.Pos) (*Var, - } else { - // If there are type parameters, rbase must denote a generic base type. - // Important: rbase must be resolved before declaring any receiver type -- // parameters (wich may have the same name, see below). -+ // parameters (which may have the same name, see below). - var baseType *Named // nil if not valid - var cause string - if t := check.genericType(rbase, &cause); isValid(t) { -diff --git a/src/internal/exportdata/exportdata.go b/src/internal/exportdata/exportdata.go -index 27675923b5..861a47f49f 100644 ---- a/src/internal/exportdata/exportdata.go -+++ b/src/internal/exportdata/exportdata.go -@@ -85,6 +85,7 @@ func ReadUnified(r *bufio.Reader) (data []byte, err error) { - - if n < 0 { - err = fmt.Errorf("invalid size (%d) in the archive file: %d bytes remain without section headers (recompile package)", size, n) -+ return - } - - // Read n bytes from buf. -diff --git a/src/internal/fuzz/mutators_byteslice_test.go b/src/internal/fuzz/mutators_byteslice_test.go -index 56adca2537..b12ef6cbcd 100644 ---- a/src/internal/fuzz/mutators_byteslice_test.go -+++ b/src/internal/fuzz/mutators_byteslice_test.go -@@ -34,12 +34,6 @@ func (mr *mockRand) uint32n(n uint32) uint32 { - return uint32(c) % n - } - --func (mr *mockRand) exp2() int { -- c := mr.values[mr.counter] -- mr.counter++ -- return c --} -- - func (mr *mockRand) bool() bool { - b := mr.b - mr.b = !mr.b -diff --git a/src/internal/fuzz/pcg.go b/src/internal/fuzz/pcg.go -index dc07b9f5bd..b8251043f1 100644 ---- a/src/internal/fuzz/pcg.go -+++ b/src/internal/fuzz/pcg.go -@@ -17,7 +17,6 @@ type mutatorRand interface { - uint32() uint32 - intn(int) int - uint32n(uint32) uint32 -- exp2() int - bool() bool - - save(randState, randInc *uint64) -@@ -123,11 +122,6 @@ func (r *pcgRand) uint32n(n uint32) uint32 { - return uint32(prod >> 32) - } - --// exp2 generates n with probability 1/2^(n+1). --func (r *pcgRand) exp2() int { -- return bits.TrailingZeros32(r.uint32()) --} -- - // bool generates a random bool. - func (r *pcgRand) bool() bool { - return r.uint32()&1 == 0 -diff --git a/src/internal/goexperiment/exp_synctest_off.go b/src/internal/goexperiment/exp_synctest_off.go -new file mode 100644 -index 0000000000..fade13f89c ---- /dev/null -+++ b/src/internal/goexperiment/exp_synctest_off.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.synctest -+ -+package goexperiment -+ -+const Synctest = false -+const SynctestInt = 0 -diff --git a/src/internal/goexperiment/exp_synctest_on.go b/src/internal/goexperiment/exp_synctest_on.go -new file mode 100644 -index 0000000000..9c44be7276 ---- /dev/null -+++ b/src/internal/goexperiment/exp_synctest_on.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.synctest -+ -+package goexperiment -+ -+const Synctest = true -+const SynctestInt = 1 -diff --git a/src/internal/pkgbits/encoder.go b/src/internal/pkgbits/encoder.go -index c17a12399d..015842f58c 100644 ---- a/src/internal/pkgbits/encoder.go -+++ b/src/internal/pkgbits/encoder.go -@@ -6,7 +6,7 @@ package pkgbits - - import ( - "bytes" -- "crypto/md5" -+ "crypto/sha256" - "encoding/binary" - "go/constant" - "io" -@@ -55,7 +55,7 @@ func NewPkgEncoder(version Version, syncFrames int) PkgEncoder { - // DumpTo writes the package's encoded data to out0 and returns the - // package fingerprint. - func (pw *PkgEncoder) DumpTo(out0 io.Writer) (fingerprint [8]byte) { -- h := md5.New() -+ h := sha256.New() - out := io.MultiWriter(out0, h) - - writeUint32 := func(x uint32) { -diff --git a/src/internal/runtime/maps/map.go b/src/internal/runtime/maps/map.go -index ffafcacdea..62463351c7 100644 ---- a/src/internal/runtime/maps/map.go -+++ b/src/internal/runtime/maps/map.go -@@ -194,6 +194,7 @@ func h2(h uintptr) uintptr { - type Map struct { - // The number of filled slots (i.e. the number of elements in all - // tables). Excludes deleted slots. -+ // Must be first (known by the compiler, for len() builtin). - used uint64 - - // seed is the hash seed, computed as a unique random number per map. -diff --git a/src/internal/sync/hashtriemap.go b/src/internal/sync/hashtriemap.go -index d31d81df39..6f5e0b437f 100644 ---- a/src/internal/sync/hashtriemap.go -+++ b/src/internal/sync/hashtriemap.go -@@ -79,7 +79,7 @@ func (ht *HashTrieMap[K, V]) Load(key K) (value V, ok bool) { - } - i = n.indirect() - } -- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") -+ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") - } - - // LoadOrStore returns the existing value for the key if present. -@@ -120,7 +120,7 @@ func (ht *HashTrieMap[K, V]) LoadOrStore(key K, value V) (result V, loaded bool) - i = n.indirect() - } - if !haveInsertPoint { -- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") -+ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") - } - - // Grab the lock and double-check what we saw. -@@ -178,7 +178,7 @@ func (ht *HashTrieMap[K, V]) expand(oldEntry, newEntry *entry[K, V], newHash uin - top := newIndirect - for { - if hashShift == 0 { -- panic("internal/concurrent.HashMapTrie: ran out of hash bits while inserting") -+ panic("internal/sync.HashTrieMap: ran out of hash bits while inserting") - } - hashShift -= nChildrenLog2 // hashShift is for the level parent is at. We need to go deeper. - oi := (oldHash >> hashShift) & nChildrenMask -@@ -219,26 +219,16 @@ func (ht *HashTrieMap[K, V]) Swap(key K, new V) (previous V, loaded bool) { - - slot = &i.children[(hash>>hashShift)&nChildrenMask] - n = slot.Load() -- if n == nil { -+ if n == nil || n.isEntry { - // We found a nil slot which is a candidate for insertion, - // or an existing entry that we'll replace. - haveInsertPoint = true - break - } -- if n.isEntry { -- // Swap if the keys compare. -- old, swapped := n.entry().swap(key, new) -- if swapped { -- return old, true -- } -- // If we fail, that means we should try to insert. -- haveInsertPoint = true -- break -- } - i = n.indirect() - } - if !haveInsertPoint { -- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") -+ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") - } - - // Grab the lock and double-check what we saw. -@@ -261,10 +251,11 @@ func (ht *HashTrieMap[K, V]) Swap(key K, new V) (previous V, loaded bool) { - var zero V - var oldEntry *entry[K, V] - if n != nil { -- // Between before and now, something got inserted. Swap if the keys compare. -+ // Swap if the keys compare. - oldEntry = n.entry() -- old, swapped := oldEntry.swap(key, new) -+ newEntry, old, swapped := oldEntry.swap(key, new) - if swapped { -+ slot.Store(&newEntry.node) - return old, true - } - } -@@ -292,30 +283,25 @@ func (ht *HashTrieMap[K, V]) CompareAndSwap(key K, old, new V) (swapped bool) { - panic("called CompareAndSwap when value is not of comparable type") - } - hash := ht.keyHash(abi.NoEscape(unsafe.Pointer(&key)), ht.seed) -- for { -- // Find the key or return if it's not there. -- i := ht.root.Load() -- hashShift := 8 * goarch.PtrSize -- found := false -- for hashShift != 0 { -- hashShift -= nChildrenLog2 - -- slot := &i.children[(hash>>hashShift)&nChildrenMask] -- n := slot.Load() -- if n == nil { -- // Nothing to compare with. Give up. -- return false -- } -- if n.isEntry { -- // We found an entry. Try to compare and swap directly. -- return n.entry().compareAndSwap(key, old, new, ht.valEqual) -- } -- i = n.indirect() -- } -- if !found { -- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") -- } -+ // Find a node with the key and compare with it. n != nil if we found the node. -+ i, _, slot, n := ht.find(key, hash, ht.valEqual, old) -+ if i != nil { -+ defer i.mu.Unlock() -+ } -+ if n == nil { -+ return false -+ } -+ -+ // Try to swap the entry. -+ e, swapped := n.entry().compareAndSwap(key, old, new, ht.valEqual) -+ if !swapped { -+ // Nothing was actually swapped, which means the node is no longer there. -+ return false - } -+ // Store the entry back because it changed. -+ slot.Store(&e.node) -+ return true - } - - // LoadAndDelete deletes the value for a key, returning the previous value if any. -@@ -353,7 +339,7 @@ func (ht *HashTrieMap[K, V]) LoadAndDelete(key K) (value V, loaded bool) { - // Check if the node is now empty (and isn't the root), and delete it if able. - for i.parent != nil && i.empty() { - if hashShift == 8*goarch.PtrSize { -- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") -+ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") - } - hashShift += nChildrenLog2 - -@@ -415,7 +401,7 @@ func (ht *HashTrieMap[K, V]) CompareAndDelete(key K, old V) (deleted bool) { - // Check if the node is now empty (and isn't the root), and delete it if able. - for i.parent != nil && i.empty() { - if hashShift == 8*goarch.PtrSize { -- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") -+ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") - } - hashShift += nChildrenLog2 - -@@ -468,7 +454,7 @@ func (ht *HashTrieMap[K, V]) find(key K, hash uintptr, valEqual equalFunc, value - i = n.indirect() - } - if !found { -- panic("internal/concurrent.HashMapTrie: ran out of hash bits while iterating") -+ panic("internal/sync.HashTrieMap: ran out of hash bits while iterating") - } - - // Grab the lock and double-check what we saw. -@@ -523,7 +509,7 @@ func (ht *HashTrieMap[K, V]) iter(i *indirect[K, V], yield func(key K, value V) - } - e := n.entry() - for e != nil { -- if !yield(e.key, *e.value.Load()) { -+ if !yield(e.key, e.value) { - return false - } - e = e.overflow.Load() -@@ -579,22 +565,21 @@ type entry[K comparable, V any] struct { - node[K, V] - overflow atomic.Pointer[entry[K, V]] // Overflow for hash collisions. - key K -- value atomic.Pointer[V] -+ value V - } - - func newEntryNode[K comparable, V any](key K, value V) *entry[K, V] { -- e := &entry[K, V]{ -- node: node[K, V]{isEntry: true}, -- key: key, -+ return &entry[K, V]{ -+ node: node[K, V]{isEntry: true}, -+ key: key, -+ value: value, - } -- e.value.Store(&value) -- return e - } - - func (e *entry[K, V]) lookup(key K) (V, bool) { - for e != nil { - if e.key == key { -- return *e.value.Load(), true -+ return e.value, true - } - e = e.overflow.Load() - } -@@ -603,87 +588,69 @@ func (e *entry[K, V]) lookup(key K) (V, bool) { - - func (e *entry[K, V]) lookupWithValue(key K, value V, valEqual equalFunc) (V, bool) { - for e != nil { -- oldp := e.value.Load() -- if e.key == key && (valEqual == nil || valEqual(unsafe.Pointer(oldp), abi.NoEscape(unsafe.Pointer(&value)))) { -- return *oldp, true -+ if e.key == key && (valEqual == nil || valEqual(unsafe.Pointer(&e.value), abi.NoEscape(unsafe.Pointer(&value)))) { -+ return e.value, true - } - e = e.overflow.Load() - } - return *new(V), false - } - --// swap replaces a value in the overflow chain if keys compare equal. --// Returns the old value, and whether or not anything was swapped. -+// swap replaces an entry in the overflow chain if keys compare equal. Returns the new entry chain, -+// the old value, and whether or not anything was swapped. - // - // swap must be called under the mutex of the indirect node which e is a child of. --func (head *entry[K, V]) swap(key K, newv V) (V, bool) { -+func (head *entry[K, V]) swap(key K, new V) (*entry[K, V], V, bool) { - if head.key == key { -- vp := new(V) -- *vp = newv -- oldp := head.value.Swap(vp) -- return *oldp, true -+ // Return the new head of the list. -+ e := newEntryNode(key, new) -+ if chain := head.overflow.Load(); chain != nil { -+ e.overflow.Store(chain) -+ } -+ return e, head.value, true - } - i := &head.overflow - e := i.Load() - for e != nil { - if e.key == key { -- vp := new(V) -- *vp = newv -- oldp := e.value.Swap(vp) -- return *oldp, true -+ eNew := newEntryNode(key, new) -+ eNew.overflow.Store(e.overflow.Load()) -+ i.Store(eNew) -+ return head, e.value, true - } - i = &e.overflow - e = e.overflow.Load() - } - var zero V -- return zero, false -+ return head, zero, false - } - --// compareAndSwap replaces a value for a matching key and existing value in the overflow chain. --// Returns whether or not anything was swapped. -+// compareAndSwap replaces an entry in the overflow chain if both the key and value compare -+// equal. Returns the new entry chain and whether or not anything was swapped. - // - // compareAndSwap must be called under the mutex of the indirect node which e is a child of. --func (head *entry[K, V]) compareAndSwap(key K, oldv, newv V, valEqual equalFunc) bool { -- var vbox *V --outerLoop: -- for { -- oldvp := head.value.Load() -- if head.key == key && valEqual(unsafe.Pointer(oldvp), abi.NoEscape(unsafe.Pointer(&oldv))) { -- // Return the new head of the list. -- if vbox == nil { -- // Delay explicit creation of a new value to hold newv. If we just pass &newv -- // to CompareAndSwap, then newv will unconditionally escape, even if the CAS fails. -- vbox = new(V) -- *vbox = newv -- } -- if head.value.CompareAndSwap(oldvp, vbox) { -- return true -- } -- // We need to restart from the head of the overflow list in case, due to a removal, a node -- // is moved up the list and we miss it. -- continue outerLoop -+func (head *entry[K, V]) compareAndSwap(key K, old, new V, valEqual equalFunc) (*entry[K, V], bool) { -+ if head.key == key && valEqual(unsafe.Pointer(&head.value), abi.NoEscape(unsafe.Pointer(&old))) { -+ // Return the new head of the list. -+ e := newEntryNode(key, new) -+ if chain := head.overflow.Load(); chain != nil { -+ e.overflow.Store(chain) - } -- i := &head.overflow -- e := i.Load() -- for e != nil { -- oldvp := e.value.Load() -- if e.key == key && valEqual(unsafe.Pointer(oldvp), abi.NoEscape(unsafe.Pointer(&oldv))) { -- if vbox == nil { -- // Delay explicit creation of a new value to hold newv. If we just pass &newv -- // to CompareAndSwap, then newv will unconditionally escape, even if the CAS fails. -- vbox = new(V) -- *vbox = newv -- } -- if e.value.CompareAndSwap(oldvp, vbox) { -- return true -- } -- continue outerLoop -- } -- i = &e.overflow -- e = e.overflow.Load() -+ return e, true -+ } -+ i := &head.overflow -+ e := i.Load() -+ for e != nil { -+ if e.key == key && valEqual(unsafe.Pointer(&e.value), abi.NoEscape(unsafe.Pointer(&old))) { -+ eNew := newEntryNode(key, new) -+ eNew.overflow.Store(e.overflow.Load()) -+ i.Store(eNew) -+ return head, true - } -- return false -+ i = &e.overflow -+ e = e.overflow.Load() - } -+ return head, false - } - - // loadAndDelete deletes an entry in the overflow chain by key. Returns the value for the key, the new -@@ -693,14 +660,14 @@ outerLoop: - func (head *entry[K, V]) loadAndDelete(key K) (V, *entry[K, V], bool) { - if head.key == key { - // Drop the head of the list. -- return *head.value.Load(), head.overflow.Load(), true -+ return head.value, head.overflow.Load(), true - } - i := &head.overflow - e := i.Load() - for e != nil { - if e.key == key { - i.Store(e.overflow.Load()) -- return *e.value.Load(), head, true -+ return e.value, head, true - } - i = &e.overflow - e = e.overflow.Load() -@@ -713,14 +680,14 @@ func (head *entry[K, V]) loadAndDelete(key K) (V, *entry[K, V], bool) { - // - // compareAndDelete must be called under the mutex of the indirect node which e is a child of. - func (head *entry[K, V]) compareAndDelete(key K, value V, valEqual equalFunc) (*entry[K, V], bool) { -- if head.key == key && valEqual(unsafe.Pointer(head.value.Load()), abi.NoEscape(unsafe.Pointer(&value))) { -+ if head.key == key && valEqual(unsafe.Pointer(&head.value), abi.NoEscape(unsafe.Pointer(&value))) { - // Drop the head of the list. - return head.overflow.Load(), true - } - i := &head.overflow - e := i.Load() - for e != nil { -- if e.key == key && valEqual(unsafe.Pointer(e.value.Load()), abi.NoEscape(unsafe.Pointer(&value))) { -+ if e.key == key && valEqual(unsafe.Pointer(&e.value), abi.NoEscape(unsafe.Pointer(&value))) { - i.Store(e.overflow.Load()) - return head, true - } -diff --git a/src/internal/sync/hashtriemap_test.go b/src/internal/sync/hashtriemap_test.go -index 5476add880..d9219f841a 100644 ---- a/src/internal/sync/hashtriemap_test.go -+++ b/src/internal/sync/hashtriemap_test.go -@@ -12,6 +12,7 @@ import ( - "strconv" - "sync" - "testing" -+ "weak" - ) - - func TestHashTrieMap(t *testing.T) { -@@ -921,3 +922,61 @@ func init() { - testDataLarge[i] = fmt.Sprintf("%b", i) - } - } -+ -+// TestConcurrentCache tests HashTrieMap in a scenario where it is used as -+// the basis of a memory-efficient concurrent cache. We're specifically -+// looking to make sure that CompareAndSwap and CompareAndDelete are -+// atomic with respect to one another. When competing for the same -+// key-value pair, they must not both succeed. -+// -+// This test is a regression test for issue #70970. -+func TestConcurrentCache(t *testing.T) { -+ type dummy [32]byte -+ -+ var m isync.HashTrieMap[int, weak.Pointer[dummy]] -+ -+ type cleanupArg struct { -+ key int -+ value weak.Pointer[dummy] -+ } -+ cleanup := func(arg cleanupArg) { -+ m.CompareAndDelete(arg.key, arg.value) -+ } -+ get := func(m *isync.HashTrieMap[int, weak.Pointer[dummy]], key int) *dummy { -+ nv := new(dummy) -+ nw := weak.Make(nv) -+ for { -+ w, loaded := m.LoadOrStore(key, nw) -+ if !loaded { -+ runtime.AddCleanup(nv, cleanup, cleanupArg{key, nw}) -+ return nv -+ } -+ if v := w.Value(); v != nil { -+ return v -+ } -+ -+ // Weak pointer was reclaimed, try to replace it with nw. -+ if m.CompareAndSwap(key, w, nw) { -+ runtime.AddCleanup(nv, cleanup, cleanupArg{key, nw}) -+ return nv -+ } -+ } -+ } -+ -+ const N = 100_000 -+ const P = 5_000 -+ -+ var wg sync.WaitGroup -+ wg.Add(N) -+ for i := range N { -+ go func() { -+ defer wg.Done() -+ a := get(&m, i%P) -+ b := get(&m, i%P) -+ if a != b { -+ t.Errorf("consecutive cache reads returned different values: a != b (%p vs %p)\n", a, b) -+ } -+ }() -+ } -+ wg.Wait() -+} -diff --git a/src/internal/syscall/unix/at_fstatat.go b/src/internal/syscall/unix/at_fstatat.go -index 25de336a80..18cd62be20 100644 ---- a/src/internal/syscall/unix/at_fstatat.go -+++ b/src/internal/syscall/unix/at_fstatat.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build dragonfly || (linux && !loong64) || netbsd || (openbsd && mips64) -+//go:build dragonfly || (linux && !(loong64 || mips64 || mips64le)) || netbsd || (openbsd && mips64) - - package unix - -diff --git a/src/internal/syscall/unix/at_fstatat2.go b/src/internal/syscall/unix/at_fstatat2.go -index 8d20e1a885..b09aecbcdd 100644 ---- a/src/internal/syscall/unix/at_fstatat2.go -+++ b/src/internal/syscall/unix/at_fstatat2.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build freebsd || (linux && loong64) -+//go:build freebsd || (linux && (loong64 || mips64 || mips64le)) - - package unix - -diff --git a/src/iter/iter.go b/src/iter/iter.go -index 14fd8f8115..e765378ef2 100644 ---- a/src/iter/iter.go -+++ b/src/iter/iter.go -@@ -28,7 +28,22 @@ or index-value pairs. - Yield returns true if the iterator should continue with the next - element in the sequence, false if it should stop. - --Iterator functions are most often called by a range loop, as in: -+For instance, [maps.Keys] returns an iterator that produces the sequence -+of keys of the map m, implemented as follows: -+ -+ func Keys[Map ~map[K]V, K comparable, V any](m Map) iter.Seq[K] { -+ return func(yield func(K) bool) { -+ for k := range m { -+ if !yield(k) { -+ return -+ } -+ } -+ } -+ } -+ -+Further examples can be found in [The Go Blog: Range Over Function Types]. -+ -+Iterator functions are most often called by a [range loop], as in: - - func PrintAll[V any](seq iter.Seq[V]) { - for v := range seq { -@@ -187,6 +202,9 @@ And then a client could delete boring values from the tree using: - p.Delete() - } - } -+ -+[The Go Blog: Range Over Function Types]: https://go.dev/blog/range-functions -+[range loop]: https://go.dev/ref/spec#For_range - */ - package iter - -diff --git a/src/net/example_test.go b/src/net/example_test.go -index 2c045d73a2..12c8397094 100644 ---- a/src/net/example_test.go -+++ b/src/net/example_test.go -@@ -334,7 +334,7 @@ func ExampleIP_To16() { - // 10.255.0.0 - } - --func ExampleIP_to4() { -+func ExampleIP_To4() { - ipv6 := net.IP{0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - ipv4 := net.IPv4(10, 255, 0, 0) - -diff --git a/src/net/http/request.go b/src/net/http/request.go -index 686d53345a..434c1640f3 100644 ---- a/src/net/http/request.go -+++ b/src/net/http/request.go -@@ -873,9 +873,9 @@ func NewRequest(method, url string, body io.Reader) (*Request, error) { - // - // NewRequestWithContext returns a Request suitable for use with - // [Client.Do] or [Transport.RoundTrip]. To create a request for use with --// testing a Server Handler, either use the [NewRequest] function in the --// net/http/httptest package, use [ReadRequest], or manually update the --// Request fields. For an outgoing client request, the context -+// testing a Server Handler, either use the [net/http/httptest.NewRequest] function, -+// use [ReadRequest], or manually update the Request fields. -+// For an outgoing client request, the context - // controls the entire lifetime of a request and its response: - // obtaining a connection, sending the request, and reading the - // response headers and body. See the Request type's documentation for -diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go -index 2963255b87..a454db5e03 100644 ---- a/src/net/http/transport_test.go -+++ b/src/net/http/transport_test.go -@@ -5500,7 +5500,9 @@ timeoutLoop: - return false - } - } -- res.Body.Close() -+ if err == nil { -+ res.Body.Close() -+ } - conns := idleConns() - if len(conns) != 1 { - if len(conns) == 0 { -diff --git a/src/net/lookup.go b/src/net/lookup.go -index b04dfa23b9..f94fd8cefa 100644 ---- a/src/net/lookup.go -+++ b/src/net/lookup.go -@@ -614,6 +614,9 @@ func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) { - - // LookupTXT returns the DNS TXT records for the given domain name. - // -+// If a DNS TXT record holds multiple strings, they are concatenated as a -+// single string. -+// - // LookupTXT uses [context.Background] internally; to specify the context, use - // [Resolver.LookupTXT]. - func LookupTXT(name string) ([]string, error) { -@@ -621,6 +624,9 @@ func LookupTXT(name string) ([]string, error) { - } - - // LookupTXT returns the DNS TXT records for the given domain name. -+// -+// If a DNS TXT record holds multiple strings, they are concatenated as a -+// single string. - func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) { - return r.lookupTXT(ctx, name) - } -diff --git a/src/os/dir.go b/src/os/dir.go -index 04392193aa..939b208d8c 100644 ---- a/src/os/dir.go -+++ b/src/os/dir.go -@@ -145,6 +145,9 @@ func ReadDir(name string) ([]DirEntry, error) { - // - // Symbolic links in dir are followed. - // -+// New files added to fsys (including if dir is a subdirectory of fsys) -+// while CopyFS is running are not guaranteed to be copied. -+// - // Copying stops at and returns the first error encountered. - func CopyFS(dir string, fsys fs.FS) error { - return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { -diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go -index 268ddb59c9..236c32ea34 100644 ---- a/src/runtime/crash_test.go -+++ b/src/runtime/crash_test.go -@@ -32,8 +32,11 @@ const entrypointVar = "RUNTIME_TEST_ENTRYPOINT" - - func TestMain(m *testing.M) { - switch entrypoint := os.Getenv(entrypointVar); entrypoint { -- case "crash": -- crash() -+ case "panic": -+ crashViaPanic() -+ panic("unreachable") -+ case "trap": -+ crashViaTrap() - panic("unreachable") - default: - log.Fatalf("invalid %s: %q", entrypointVar, entrypoint) -diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go -index 35cb634936..00280ed1b5 100644 ---- a/src/runtime/gc_test.go -+++ b/src/runtime/gc_test.go -@@ -834,7 +834,11 @@ func TestWeakToStrongMarkTermination(t *testing.T) { - done <- struct{}{} - }() - go func() { -- time.Sleep(100 * time.Millisecond) -+ // Usleep here instead of time.Sleep. time.Sleep -+ // can allocate, and if we get unlucky, then it -+ // can end up stuck in gcMarkDone with nothing to -+ // wake it. -+ runtime.Usleep(100000) // 100ms - - // Let mark termination continue. - runtime.SetSpinInGCMarkDone(false) -diff --git a/src/runtime/map_swiss.go b/src/runtime/map_swiss.go -index 75c72b20f5..e6e29bcfb8 100644 ---- a/src/runtime/map_swiss.go -+++ b/src/runtime/map_swiss.go -@@ -39,6 +39,16 @@ func makemap64(t *abi.SwissMapType, hint int64, m *maps.Map) *maps.Map { - // makemap_small implements Go map creation for make(map[k]v) and - // make(map[k]v, hint) when hint is known to be at most abi.SwissMapGroupSlots - // at compile time and the map needs to be allocated on the heap. -+// -+// makemap_small should be an internal detail, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/bytedance/sonic -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// -+//go:linkname makemap_small - func makemap_small() *maps.Map { - return maps.NewEmptyMap() - } -@@ -48,6 +58,16 @@ func makemap_small() *maps.Map { - // can be created on the stack, m and optionally m.dirPtr may be non-nil. - // If m != nil, the map can be created directly in m. - // If m.dirPtr != nil, it points to a group usable for a small map. -+// -+// makemap should be an internal detail, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/ugorji/go/codec -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// -+//go:linkname makemap - func makemap(t *abi.SwissMapType, hint int, m *maps.Map) *maps.Map { - if hint < 0 { - hint = 0 -@@ -68,6 +88,15 @@ func makemap(t *abi.SwissMapType, hint int, m *maps.Map) *maps.Map { - //go:linkname mapaccess1 - func mapaccess1(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) unsafe.Pointer - -+// mapaccess2 should be an internal detail, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/ugorji/go/codec -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// -+//go:linkname mapaccess2 - func mapaccess2(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) (unsafe.Pointer, bool) - - func mapaccess1_fat(t *abi.SwissMapType, m *maps.Map, key, zero unsafe.Pointer) unsafe.Pointer { -@@ -89,9 +118,29 @@ func mapaccess2_fat(t *abi.SwissMapType, m *maps.Map, key, zero unsafe.Pointer) - // mapassign is pushed from internal/runtime/maps. We could just call it, but - // we want to avoid one layer of call. - // -+// mapassign should be an internal detail, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/bytedance/sonic -+// - github.com/RomiChan/protobuf -+// - github.com/segmentio/encoding -+// - github.com/ugorji/go/codec -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// - //go:linkname mapassign - func mapassign(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) unsafe.Pointer - -+// mapdelete should be an internal detail, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/ugorji/go/codec -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// -+//go:linkname mapdelete - func mapdelete(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) { - if raceenabled && m != nil { - callerpc := sys.GetCallerPC() -@@ -113,6 +162,21 @@ func mapdelete(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) { - // The Iter struct pointed to by 'it' is allocated on the stack - // by the compilers order pass or on the heap by reflect_mapiterinit. - // Both need to have zeroed hiter since the struct contains pointers. -+// -+// mapiterinit should be an internal detail, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/bytedance/sonic -+// - github.com/goccy/go-json -+// - github.com/RomiChan/protobuf -+// - github.com/segmentio/encoding -+// - github.com/ugorji/go/codec -+// - github.com/wI2L/jettison -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// -+//go:linkname mapiterinit - func mapiterinit(t *abi.SwissMapType, m *maps.Map, it *maps.Iter) { - if raceenabled && m != nil { - callerpc := sys.GetCallerPC() -@@ -123,6 +187,19 @@ func mapiterinit(t *abi.SwissMapType, m *maps.Map, it *maps.Iter) { - it.Next() - } - -+// mapiternext should be an internal detail, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/bytedance/sonic -+// - github.com/RomiChan/protobuf -+// - github.com/segmentio/encoding -+// - github.com/ugorji/go/codec -+// - gonum.org/v1/gonum -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// -+//go:linkname mapiternext - func mapiternext(it *maps.Iter) { - if raceenabled { - callerpc := sys.GetCallerPC() -@@ -145,6 +222,19 @@ func mapclear(t *abi.SwissMapType, m *maps.Map) { - - // Reflect stubs. Called from ../reflect/asm_*.s - -+// reflect_makemap is for package reflect, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - gitee.com/quant1x/gox -+// - github.com/modern-go/reflect2 -+// - github.com/goccy/go-json -+// - github.com/RomiChan/protobuf -+// - github.com/segmentio/encoding -+// - github.com/v2pro/plz -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// - //go:linkname reflect_makemap reflect.makemap - func reflect_makemap(t *abi.SwissMapType, cap int) *maps.Map { - // Check invariants and reflects math. -@@ -156,6 +246,16 @@ func reflect_makemap(t *abi.SwissMapType, cap int) *maps.Map { - return makemap(t, cap, nil) - } - -+// reflect_mapaccess is for package reflect, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - gitee.com/quant1x/gox -+// - github.com/modern-go/reflect2 -+// - github.com/v2pro/plz -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// - //go:linkname reflect_mapaccess reflect.mapaccess - func reflect_mapaccess(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) unsafe.Pointer { - elem, ok := mapaccess2(t, m, key) -@@ -176,6 +276,14 @@ func reflect_mapaccess_faststr(t *abi.SwissMapType, m *maps.Map, key string) uns - return elem - } - -+// reflect_mapassign is for package reflect, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - gitee.com/quant1x/gox -+// - github.com/v2pro/plz -+// -+// Do not remove or change the type signature. -+// - //go:linkname reflect_mapassign reflect.mapassign0 - func reflect_mapassign(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer, elem unsafe.Pointer) { - p := mapassign(t, m, key) -@@ -198,26 +306,76 @@ func reflect_mapdelete_faststr(t *abi.SwissMapType, m *maps.Map, key string) { - mapdelete_faststr(t, m, key) - } - -+// reflect_mapiterinit is for package reflect, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/modern-go/reflect2 -+// - gitee.com/quant1x/gox -+// - github.com/v2pro/plz -+// - github.com/wI2L/jettison -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// - //go:linkname reflect_mapiterinit reflect.mapiterinit - func reflect_mapiterinit(t *abi.SwissMapType, m *maps.Map, it *maps.Iter) { - mapiterinit(t, m, it) - } - -+// reflect_mapiternext is for package reflect, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - gitee.com/quant1x/gox -+// - github.com/modern-go/reflect2 -+// - github.com/goccy/go-json -+// - github.com/v2pro/plz -+// - github.com/wI2L/jettison -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// - //go:linkname reflect_mapiternext reflect.mapiternext - func reflect_mapiternext(it *maps.Iter) { - mapiternext(it) - } - -+// reflect_mapiterkey was for package reflect, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/goccy/go-json -+// - gonum.org/v1/gonum -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// - //go:linkname reflect_mapiterkey reflect.mapiterkey - func reflect_mapiterkey(it *maps.Iter) unsafe.Pointer { - return it.Key() - } - -+// reflect_mapiterelem was for package reflect, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/goccy/go-json -+// - gonum.org/v1/gonum -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// - //go:linkname reflect_mapiterelem reflect.mapiterelem - func reflect_mapiterelem(it *maps.Iter) unsafe.Pointer { - return it.Elem() - } - -+// reflect_maplen is for package reflect, -+// but widely used packages access it using linkname. -+// Notable members of the hall of shame include: -+// - github.com/goccy/go-json -+// - github.com/wI2L/jettison -+// -+// Do not remove or change the type signature. -+// See go.dev/issue/67401. -+// - //go:linkname reflect_maplen reflect.maplen - func reflect_maplen(m *maps.Map) int { - if m == nil { -diff --git a/src/runtime/pprof/vminfo_darwin_test.go b/src/runtime/pprof/vminfo_darwin_test.go -index 4c0a0fefd8..6d375c5d53 100644 ---- a/src/runtime/pprof/vminfo_darwin_test.go -+++ b/src/runtime/pprof/vminfo_darwin_test.go -@@ -97,7 +97,7 @@ func useVMMap(t *testing.T) (hi, lo uint64, retryable bool, err error) { - t.Logf("vmmap output: %s", out) - if ee, ok := cmdErr.(*exec.ExitError); ok && len(ee.Stderr) > 0 { - t.Logf("%v: %v\n%s", cmd, cmdErr, ee.Stderr) -- if testing.Short() && strings.Contains(string(ee.Stderr), "No process corpse slots currently available, waiting to get one") { -+ if testing.Short() && (strings.Contains(string(ee.Stderr), "No process corpse slots currently available, waiting to get one") || strings.Contains(string(ee.Stderr), "Failed to generate corpse from the process")) { - t.Skipf("Skipping knwn flake in short test mode") - } - retryable = bytes.Contains(ee.Stderr, []byte("resource shortage")) -diff --git a/src/runtime/proc.go b/src/runtime/proc.go -index 6362960200..e9873e54cd 100644 ---- a/src/runtime/proc.go -+++ b/src/runtime/proc.go -@@ -3894,23 +3894,23 @@ func injectglist(glist *gList) { - if glist.empty() { - return - } -- trace := traceAcquire() -- if trace.ok() { -- for gp := glist.head.ptr(); gp != nil; gp = gp.schedlink.ptr() { -- trace.GoUnpark(gp, 0) -- } -- traceRelease(trace) -- } - - // Mark all the goroutines as runnable before we put them - // on the run queues. - head := glist.head.ptr() - var tail *g - qsize := 0 -+ trace := traceAcquire() - for gp := head; gp != nil; gp = gp.schedlink.ptr() { - tail = gp - qsize++ - casgstatus(gp, _Gwaiting, _Grunnable) -+ if trace.ok() { -+ trace.GoUnpark(gp, 0) -+ } -+ } -+ if trace.ok() { -+ traceRelease(trace) - } - - // Turn the gList into a gQueue. -diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go -index c78b044264..c3bd510320 100644 ---- a/src/runtime/symtab.go -+++ b/src/runtime/symtab.go -@@ -468,6 +468,18 @@ type modulehash struct { - // To make sure the map isn't collected, we keep a second reference here. - var pinnedTypemaps []map[typeOff]*_type - -+// aixStaticDataBase (used only on AIX) holds the unrelocated address -+// of the data section, set by the linker. -+// -+// On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol -+// does not work, as the dynamic loader can change the address of the -+// data section, and it is not possible to apply a dynamic relocation -+// to RODATA. In order to get the correct address, we need to apply -+// the delta between unrelocated and relocated data section addresses. -+// aixStaticDataBase is the unrelocated address, and moduledata.data is -+// the relocated one. -+var aixStaticDataBase uintptr // linker symbol -+ - var firstmoduledata moduledata // linker symbol - var lastmoduledatap *moduledata // linker symbol - -diff --git a/src/runtime/traceback_system_test.go b/src/runtime/traceback_system_test.go -index ece58e806d..af20f54a09 100644 ---- a/src/runtime/traceback_system_test.go -+++ b/src/runtime/traceback_system_test.go -@@ -23,8 +23,8 @@ import ( - ) - - // This is the entrypoint of the child process used by --// TestTracebackSystem. It prints a crash report to stdout. --func crash() { -+// TestTracebackSystem/panic. It prints a crash report to stdout. -+func crashViaPanic() { - // Ensure that we get pc=0x%x values in the traceback. - debug.SetTraceback("system") - writeSentinel(os.Stdout) -@@ -37,6 +37,21 @@ func crash() { - select {} - } - -+// This is the entrypoint of the child process used by -+// TestTracebackSystem/trap. It prints a crash report to stdout. -+func crashViaTrap() { -+ // Ensure that we get pc=0x%x values in the traceback. -+ debug.SetTraceback("system") -+ writeSentinel(os.Stdout) -+ debug.SetCrashOutput(os.Stdout, debug.CrashOptions{}) -+ -+ go func() { -+ // This call is typically inlined. -+ trap1() -+ }() -+ select {} -+} -+ - func child1() { - child2() - } -@@ -85,6 +100,20 @@ func child7() { - panic("oops") - } - -+func trap1() { -+ trap2() -+} -+ -+var sinkPtr *int -+ -+func trap2() { -+ trap3(sinkPtr) -+} -+ -+func trap3(i *int) { -+ *i = 42 -+} -+ - // TestTracebackSystem tests that the syntax of crash reports produced - // by GOTRACEBACK=system (see traceback2) contains a complete, - // parseable list of program counters for the running goroutine that -@@ -100,46 +129,75 @@ func TestTracebackSystem(t *testing.T) { - t.Skip("Can't read source code for this file on Android") - } - -- // Fork+exec the crashing process. -- exe, err := os.Executable() -- if err != nil { -- t.Fatal(err) -- } -- cmd := testenv.Command(t, exe) -- cmd.Env = append(cmd.Environ(), entrypointVar+"=crash") -- var stdout, stderr bytes.Buffer -- cmd.Stdout = &stdout -- cmd.Stderr = &stderr -- cmd.Run() // expected to crash -- t.Logf("stderr:\n%s\nstdout: %s\n", stderr.Bytes(), stdout.Bytes()) -- crash := stdout.String() -- -- // If the only line is the sentinel, it wasn't a crash. -- if strings.Count(crash, "\n") < 2 { -- t.Fatalf("child process did not produce a crash report") -+ tests := []struct{ -+ name string -+ want string -+ }{ -+ { -+ name: "panic", -+ want: `redacted.go:0: runtime.gopanic -+traceback_system_test.go:100: runtime_test.child7: panic("oops") -+traceback_system_test.go:83: runtime_test.child6: child7() // appears in stack trace -+traceback_system_test.go:74: runtime_test.child5: child6() // appears in stack trace -+traceback_system_test.go:68: runtime_test.child4: child5() -+traceback_system_test.go:64: runtime_test.child3: child4() -+traceback_system_test.go:60: runtime_test.child2: child3() -+traceback_system_test.go:56: runtime_test.child1: child2() -+traceback_system_test.go:35: runtime_test.crashViaPanic.func1: child1() -+redacted.go:0: runtime.goexit -+`, -+ }, -+ { -+ // Test panic via trap. x/telemetry is aware that trap -+ // PCs follow runtime.sigpanic and need to be -+ // incremented to offset the decrement done by -+ // CallersFrames. -+ name: "trap", -+ want: `redacted.go:0: runtime.gopanic -+redacted.go:0: runtime.panicmem -+redacted.go:0: runtime.sigpanic -+traceback_system_test.go:114: runtime_test.trap3: *i = 42 -+traceback_system_test.go:110: runtime_test.trap2: trap3(sinkPtr) -+traceback_system_test.go:104: runtime_test.trap1: trap2() -+traceback_system_test.go:50: runtime_test.crashViaTrap.func1: trap1() -+redacted.go:0: runtime.goexit -+`, -+ }, - } - -- // Parse the PCs out of the child's crash report. -- pcs, err := parseStackPCs(crash) -- if err != nil { -- t.Fatal(err) -- } -+ for _, tc := range tests { -+ t.Run(tc.name, func(t *testing.T) { -+ // Fork+exec the crashing process. -+ exe, err := os.Executable() -+ if err != nil { -+ t.Fatal(err) -+ } -+ cmd := testenv.Command(t, exe) -+ cmd.Env = append(cmd.Environ(), entrypointVar+"="+tc.name) -+ var stdout, stderr bytes.Buffer -+ cmd.Stdout = &stdout -+ cmd.Stderr = &stderr -+ cmd.Run() // expected to crash -+ t.Logf("stderr:\n%s\nstdout: %s\n", stderr.Bytes(), stdout.Bytes()) -+ crash := stdout.String() -+ -+ // If the only line is the sentinel, it wasn't a crash. -+ if strings.Count(crash, "\n") < 2 { -+ t.Fatalf("child process did not produce a crash report") -+ } - -- // Unwind the stack using this executable's symbol table. -- got := formatStack(pcs) -- want := `redacted.go:0: runtime.gopanic --traceback_system_test.go:85: runtime_test.child7: panic("oops") --traceback_system_test.go:68: runtime_test.child6: child7() // appears in stack trace --traceback_system_test.go:59: runtime_test.child5: child6() // appears in stack trace --traceback_system_test.go:53: runtime_test.child4: child5() --traceback_system_test.go:49: runtime_test.child3: child4() --traceback_system_test.go:45: runtime_test.child2: child3() --traceback_system_test.go:41: runtime_test.child1: child2() --traceback_system_test.go:35: runtime_test.crash.func1: child1() --redacted.go:0: runtime.goexit --` -- if strings.TrimSpace(got) != strings.TrimSpace(want) { -- t.Errorf("got:\n%swant:\n%s", got, want) -+ // Parse the PCs out of the child's crash report. -+ pcs, err := parseStackPCs(crash) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ // Unwind the stack using this executable's symbol table. -+ got := formatStack(pcs) -+ if strings.TrimSpace(got) != strings.TrimSpace(tc.want) { -+ t.Errorf("got:\n%swant:\n%s", got, tc.want) -+ } -+ }) - } - } - -@@ -154,6 +212,35 @@ redacted.go:0: runtime.goexit - // - // (Copied from golang.org/x/telemetry/crashmonitor.parseStackPCs.) - func parseStackPCs(crash string) ([]uintptr, error) { -+ // getSymbol parses the symbol name out of a line of the form: -+ // SYMBOL(ARGS) -+ // -+ // Note: SYMBOL may contain parens "pkg.(*T).method". However, type -+ // parameters are always replaced with ..., so they cannot introduce -+ // more parens. e.g., "pkg.(*T[...]).method". -+ // -+ // ARGS can contain parens. We want the first paren that is not -+ // immediately preceded by a ".". -+ // -+ // TODO(prattmic): This is mildly complicated and is only used to find -+ // runtime.sigpanic, so perhaps simplify this by checking explicitly -+ // for sigpanic. -+ getSymbol := func(line string) (string, error) { -+ var prev rune -+ for i, c := range line { -+ if line[i] != '(' { -+ prev = c -+ continue -+ } -+ if prev == '.' { -+ prev = c -+ continue -+ } -+ return line[:i], nil -+ } -+ return "", fmt.Errorf("no symbol for stack frame: %s", line) -+ } -+ - // getPC parses the PC out of a line of the form: - // \tFILE:LINE +0xRELPC sp=... fp=... pc=... - getPC := func(line string) (uint64, error) { -@@ -170,6 +257,9 @@ func parseStackPCs(crash string) ([]uintptr, error) { - childSentinel = sentinel() - on = false // are we in the first running goroutine? - lines = strings.Split(crash, "\n") -+ symLine = true // within a goroutine, every other line is a symbol or file/line/pc location, starting with symbol. -+ currSymbol string -+ prevSymbol string // symbol of the most recent previous frame with a PC. - ) - for i := 0; i < len(lines); i++ { - line := lines[i] -@@ -212,21 +302,76 @@ func parseStackPCs(crash string) ([]uintptr, error) { - // Note: SYMBOL may contain parens "pkg.(*T).method" - // The RELPC is sometimes missing. - -- // Skip the symbol(args) line. -- i++ -- if i == len(lines) { -- break -- } -- line = lines[i] -+ if symLine { -+ var err error -+ currSymbol, err = getSymbol(line) -+ if err != nil { -+ return nil, fmt.Errorf("error extracting symbol: %v", err) -+ } - -- // Parse the PC, and correct for the parent and child's -- // different mappings of the text section. -- pc, err := getPC(line) -- if err != nil { -- // Inlined frame, perhaps; skip it. -- continue -+ symLine = false // Next line is FILE:LINE. -+ } else { -+ // Parse the PC, and correct for the parent and child's -+ // different mappings of the text section. -+ pc, err := getPC(line) -+ if err != nil { -+ // Inlined frame, perhaps; skip it. -+ -+ // Done with this frame. Next line is a new frame. -+ // -+ // Don't update prevSymbol; we only want to -+ // track frames with a PC. -+ currSymbol = "" -+ symLine = true -+ continue -+ } -+ -+ pc = pc-parentSentinel+childSentinel -+ -+ // If the previous frame was sigpanic, then this frame -+ // was a trap (e.g., SIGSEGV). -+ // -+ // Typically all middle frames are calls, and report -+ // the "return PC". That is, the instruction following -+ // the CALL where the callee will eventually return to. -+ // -+ // runtime.CallersFrames is aware of this property and -+ // will decrement each PC by 1 to "back up" to the -+ // location of the CALL, which is the actual line -+ // number the user expects. -+ // -+ // This does not work for traps, as a trap is not a -+ // call, so the reported PC is not the return PC, but -+ // the actual PC of the trap. -+ // -+ // runtime.Callers is aware of this and will -+ // intentionally increment trap PCs in order to correct -+ // for the decrement performed by -+ // runtime.CallersFrames. See runtime.tracebackPCs and -+ // runtume.(*unwinder).symPC. -+ // -+ // We must emulate the same behavior, otherwise we will -+ // report the location of the instruction immediately -+ // prior to the trap, which may be on a different line, -+ // or even a different inlined functions. -+ // -+ // TODO(prattmic): The runtime applies the same trap -+ // behavior for other "injected calls", see injectCall -+ // in runtime.(*unwinder).next. Do we want to handle -+ // those as well? I don't believe we'd ever see -+ // runtime.asyncPreempt or runtime.debugCallV2 in a -+ // typical crash. -+ if prevSymbol == "runtime.sigpanic" { -+ pc++ -+ } -+ -+ pcs = append(pcs, uintptr(pc)) -+ -+ // Done with this frame. Next line is a new frame. -+ prevSymbol = currSymbol -+ currSymbol = "" -+ symLine = true - } -- pcs = append(pcs, uintptr(pc-parentSentinel+childSentinel)) - } - return pcs, nil - } -diff --git a/src/runtime/type.go b/src/runtime/type.go -index 9702164b1a..1edf9c9dd6 100644 ---- a/src/runtime/type.go -+++ b/src/runtime/type.go -@@ -104,6 +104,10 @@ func getGCMaskOnDemand(t *_type) *byte { - // in read-only memory currently. - addr := unsafe.Pointer(t.GCData) - -+ if GOOS == "aix" { -+ addr = add(addr, firstmoduledata.data-aixStaticDataBase) -+ } -+ - for { - p := (*byte)(atomic.Loadp(addr)) - switch p { -diff --git a/src/slices/slices.go b/src/slices/slices.go -index 40b4d088b0..32029cd8ed 100644 ---- a/src/slices/slices.go -+++ b/src/slices/slices.go -@@ -414,6 +414,7 @@ func Grow[S ~[]E, E any](s S, n int) S { - panic("cannot be negative") - } - if n -= cap(s) - len(s); n > 0 { -+ // This expression allocates only once (see test). - s = append(s[:cap(s)], make([]E, n)...)[:len(s)] - } - return s -@@ -483,6 +484,9 @@ func Concat[S ~[]E, E any](slices ...S) S { - panic("len out of range") - } - } -+ // Use Grow, not make, to round up to the size class: -+ // the extra space is otherwise unused and helps -+ // callers that append a few elements to the result. - newslice := Grow[S](nil, size) - for _, s := range slices { - newslice = append(newslice, s...) -diff --git a/src/strconv/ftoa.go b/src/strconv/ftoa.go -index 6db0d47e0f..bfe26366e1 100644 ---- a/src/strconv/ftoa.go -+++ b/src/strconv/ftoa.go -@@ -44,6 +44,8 @@ var float64info = floatInfo{52, 11, -1023} - // zeros are removed). - // The special precision -1 uses the smallest number of digits - // necessary such that ParseFloat will return f exactly. -+// The exponent is written as a decimal integer; -+// for all formats other than 'b', it will be at least two digits. - func FormatFloat(f float64, fmt byte, prec, bitSize int) string { - return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize)) - } -diff --git a/src/strings/iter.go b/src/strings/iter.go -index b9620902bf..3168e59687 100644 ---- a/src/strings/iter.go -+++ b/src/strings/iter.go -@@ -68,7 +68,7 @@ func splitSeq(s, sep string, sepSave int) iter.Seq[string] { - } - - // SplitSeq returns an iterator over all substrings of s separated by sep. --// The iterator yields the same strings that would be returned by Split(s, sep), -+// The iterator yields the same strings that would be returned by [Split](s, sep), - // but without constructing the slice. - // It returns a single-use iterator. - func SplitSeq(s, sep string) iter.Seq[string] { -@@ -76,7 +76,7 @@ func SplitSeq(s, sep string) iter.Seq[string] { - } - - // SplitAfterSeq returns an iterator over substrings of s split after each instance of sep. --// The iterator yields the same strings that would be returned by SplitAfter(s, sep), -+// The iterator yields the same strings that would be returned by [SplitAfter](s, sep), - // but without constructing the slice. - // It returns a single-use iterator. - func SplitAfterSeq(s, sep string) iter.Seq[string] { -@@ -84,8 +84,8 @@ func SplitAfterSeq(s, sep string) iter.Seq[string] { - } - - // FieldsSeq returns an iterator over substrings of s split around runs of --// whitespace characters, as defined by unicode.IsSpace. --// The iterator yields the same strings that would be returned by Fields(s), -+// whitespace characters, as defined by [unicode.IsSpace]. -+// The iterator yields the same strings that would be returned by [Fields](s), - // but without constructing the slice. - func FieldsSeq(s string) iter.Seq[string] { - return func(yield func(string) bool) { -@@ -118,7 +118,7 @@ func FieldsSeq(s string) iter.Seq[string] { - - // FieldsFuncSeq returns an iterator over substrings of s split around runs of - // Unicode code points satisfying f(c). --// The iterator yields the same strings that would be returned by FieldsFunc(s), -+// The iterator yields the same strings that would be returned by [FieldsFunc](s), - // but without constructing the slice. - func FieldsFuncSeq(s string, f func(rune) bool) iter.Seq[string] { - return func(yield func(string) bool) { -diff --git a/src/syscall/syscall_freebsd_386.go b/src/syscall/syscall_freebsd_386.go -index 60359e38f6..a217dc758b 100644 ---- a/src/syscall/syscall_freebsd_386.go -+++ b/src/syscall/syscall_freebsd_386.go -@@ -36,7 +36,13 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e - var writtenOut uint64 = 0 - _, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr((*offset)>>32), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0) - -- written = int(writtenOut) -+ // For some reason on the freebsd-386 builder writtenOut -+ // is modified when the system call returns EINVAL. -+ // The man page says that the value is only written for -+ // success, EINTR, or EAGAIN, so only use those cases. -+ if e1 == 0 || e1 == EINTR || e1 == EAGAIN { -+ written = int(writtenOut) -+ } - - if e1 != 0 { - err = e1 -diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go -index 51f5ead472..e826e08615 100644 ---- a/src/syscall/syscall_linux_mips64x.go -+++ b/src/syscall/syscall_linux_mips64x.go -@@ -16,7 +16,6 @@ const ( - //sys Dup2(oldfd int, newfd int) (err error) - //sys Fchown(fd int, uid int, gid int) (err error) - //sys Fstatfs(fd int, buf *Statfs_t) (err error) --//sys fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT - //sys Ftruncate(fd int, length int64) (err error) - //sysnb Getegid() (egid int) - //sysnb Geteuid() (euid int) -@@ -126,10 +125,22 @@ type stat_t struct { - Blocks int64 - } - -+//sys fstatatInternal(dirfd int, path string, stat *stat_t, flags int) (err error) = SYS_NEWFSTATAT - //sys fstat(fd int, st *stat_t) (err error) - //sys lstat(path string, st *stat_t) (err error) - //sys stat(path string, st *stat_t) (err error) - -+func fstatat(fd int, path string, s *Stat_t, flags int) (err error) { -+ st := &stat_t{} -+ err = fstatatInternal(fd, path, st, flags) -+ fillStat_t(s, st) -+ return -+} -+ -+func Fstatat(fd int, path string, s *Stat_t, flags int) (err error) { -+ return fstatat(fd, path, s, flags) -+} -+ - func Fstat(fd int, s *Stat_t) (err error) { - st := &stat_t{} - err = fstat(fd, st) -diff --git a/src/syscall/zsyscall_linux_mips64.go b/src/syscall/zsyscall_linux_mips64.go -index 0352ea5420..449088c815 100644 ---- a/src/syscall/zsyscall_linux_mips64.go -+++ b/src/syscall/zsyscall_linux_mips64.go -@@ -1116,21 +1116,6 @@ func Fstatfs(fd int, buf *Statfs_t) (err error) { - - // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - --func fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { -- var _p0 *byte -- _p0, err = BytePtrFromString(path) -- if err != nil { -- return -- } -- _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) -- if e1 != 0 { -- err = errnoErr(e1) -- } -- return --} -- --// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -- - func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0) - if e1 != 0 { -@@ -1638,6 +1623,21 @@ func utimes(path string, times *[2]Timeval) (err error) { - - // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -+func fstatatInternal(dirfd int, path string, stat *stat_t, flags int) (err error) { -+ var _p0 *byte -+ _p0, err = BytePtrFromString(path) -+ if err != nil { -+ return -+ } -+ _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) -+ if e1 != 0 { -+ err = errnoErr(e1) -+ } -+ return -+} -+ -+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -+ - func fstat(fd int, st *stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(st)), 0) - if e1 != 0 { -diff --git a/src/syscall/zsyscall_linux_mips64le.go b/src/syscall/zsyscall_linux_mips64le.go -index 1338b8c1c3..048298a39c 100644 ---- a/src/syscall/zsyscall_linux_mips64le.go -+++ b/src/syscall/zsyscall_linux_mips64le.go -@@ -1116,21 +1116,6 @@ func Fstatfs(fd int, buf *Statfs_t) (err error) { - - // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - --func fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { -- var _p0 *byte -- _p0, err = BytePtrFromString(path) -- if err != nil { -- return -- } -- _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) -- if e1 != 0 { -- err = errnoErr(e1) -- } -- return --} -- --// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -- - func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0) - if e1 != 0 { -@@ -1638,6 +1623,21 @@ func utimes(path string, times *[2]Timeval) (err error) { - - // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -+func fstatatInternal(dirfd int, path string, stat *stat_t, flags int) (err error) { -+ var _p0 *byte -+ _p0, err = BytePtrFromString(path) -+ if err != nil { -+ return -+ } -+ _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) -+ if e1 != 0 { -+ err = errnoErr(e1) -+ } -+ return -+} -+ -+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -+ - func fstat(fd int, st *stat_t) (err error) { - _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(st)), 0) - if e1 != 0 { -diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go -index 78e1b2de6d..3a7da9e540 100644 ---- a/src/testing/benchmark.go -+++ b/src/testing/benchmark.go -@@ -5,6 +5,7 @@ - package testing - - import ( -+ "context" - "flag" - "fmt" - "internal/sysinfo" -@@ -78,7 +79,7 @@ type InternalBenchmark struct { - } - - // B is a type passed to [Benchmark] functions to manage benchmark --// timing and to specify the number of iterations to run. -+// timing and control the number of iterations. - // - // A benchmark ends when its Benchmark function returns or calls any of the methods - // FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods must be called -@@ -133,8 +134,7 @@ func (b *B) StartTimer() { - } - - // StopTimer stops timing a test. This can be used to pause the timer --// while performing complex initialization that you don't --// want to measure. -+// while performing steps that you don't want to measure. - func (b *B) StopTimer() { - if b.timerOn { - b.duration += highPrecisionTimeSince(b.start) -@@ -182,6 +182,7 @@ func (b *B) ReportAllocs() { - func (b *B) runN(n int) { - benchmarkLock.Lock() - defer benchmarkLock.Unlock() -+ ctx, cancelCtx := context.WithCancel(context.Background()) - defer func() { - b.runCleanup(normalPanic) - b.checkRaces() -@@ -192,6 +193,8 @@ func (b *B) runN(n int) { - b.resetRaces() - b.N = n - b.loopN = 0 -+ b.ctx = ctx -+ b.cancelCtx = cancelCtx - - b.parallelism = 1 - b.ResetTimer() -@@ -367,6 +370,8 @@ func (b *B) ReportMetric(n float64, unit string) { - func (b *B) stopOrScaleBLoop() bool { - timeElapsed := highPrecisionTimeSince(b.start) - if timeElapsed >= b.benchTime.d { -+ // Stop the timer so we don't count cleanup time -+ b.StopTimer() - return false - } - // Loop scaling -@@ -387,40 +392,53 @@ func (b *B) loopSlowPath() bool { - b.ResetTimer() - return true - } -- // Handles fixed time case -+ // Handles fixed iterations case - if b.benchTime.n > 0 { - if b.N < b.benchTime.n { - b.N = b.benchTime.n - b.loopN++ - return true - } -+ b.StopTimer() - return false - } -- // Handles fixed iteration count case -+ // Handles fixed time case - return b.stopOrScaleBLoop() - } - --// Loop returns true until b.N calls has been made to it. --// --// A benchmark should either use Loop or contain an explicit loop from 0 to b.N, but not both. --// After the benchmark finishes, b.N will contain the total number of calls to op, so the benchmark --// may use b.N to compute other average metrics. -+// Loop returns true as long as the benchmark should continue running. - // --// The parameters and results of function calls inside the body of "for b.Loop() {...}" are guaranteed --// not to be optimized away. --// Also, the local loop scaling for b.Loop ensures the benchmark function containing the loop will only --// be executed once, i.e. for such construct: -+// A typical benchmark is structured like: - // --// testing.Benchmark(func(b *testing.B) { --// ...(setup) --// for b.Loop() { --// ...(benchmark logic) --// } --// ...(clean-up) -+// func Benchmark(b *testing.B) { -+// ... setup ... -+// for b.Loop() { -+// ... code to measure ... -+// } -+// ... cleanup ... - // } - // --// The ...(setup) and ...(clean-up) logic will only be executed once. --// Also benchtime=Nx (N>1) will result in exactly N executions instead of N+1 for b.N style loops. -+// Loop resets the benchmark timer the first time it is called in a benchmark, -+// so any setup performed prior to starting the benchmark loop does not count -+// toward the benchmark measurement. Likewise, when it returns false, it stops -+// the timer so cleanup code is not measured. -+// -+// The compiler never optimizes away calls to functions within the body of a -+// "for b.Loop() { ... }" loop. This prevents surprises that can otherwise occur -+// if the compiler determines that the result of a benchmarked function is -+// unused. The loop must be written in exactly this form, and this only applies -+// to calls syntactically between the curly braces of the loop. Optimizations -+// are performed as usual in any functions called by the loop. -+// -+// After Loop returns false, b.N contains the total number of iterations that -+// ran, so the benchmark may use b.N to compute other average metrics. -+// -+// Prior to the introduction of Loop, benchmarks were expected to contain an -+// explicit loop from 0 to b.N. Benchmarks should either use Loop or contain a -+// loop to b.N, but not both. Loop offers more automatic management of the -+// benchmark timer, and runs each benchmark function only once per measurement, -+// whereas b.N-based benchmarks must run the benchmark function (and any -+// associated setup and cleanup) several times. - func (b *B) Loop() bool { - if b.loopN != 0 && b.loopN < b.N { - b.loopN++ -diff --git a/src/testing/benchmark_test.go b/src/testing/benchmark_test.go -index 259b70ed4c..e2dd24c839 100644 ---- a/src/testing/benchmark_test.go -+++ b/src/testing/benchmark_test.go -@@ -7,6 +7,8 @@ package testing_test - import ( - "bytes" - "cmp" -+ "context" -+ "errors" - "runtime" - "slices" - "strings" -@@ -127,56 +129,32 @@ func TestRunParallelSkipNow(t *testing.T) { - }) - } - --func TestBLoopHasResults(t *testing.T) { -- // Verify that b.N and the b.Loop() iteration count match. -- var nIterated int -- bRet := testing.Benchmark(func(b *testing.B) { -- i := 0 -- for b.Loop() { -- i++ -- } -- nIterated = i -- }) -- if nIterated == 0 { -- t.Fatalf("Iteration count zero") -- } -- if bRet.N != nIterated { -- t.Fatalf("Benchmark result N incorrect, got %d want %d", bRet.N, nIterated) -- } -- // We only need to check duration to make sure benchmark result is written. -- if bRet.T == 0 { -- t.Fatalf("Benchmark result duration unset") -- } --} -- --func ExampleB_Loop() { -- simpleFunc := func(i int) int { -- return i + 1 -- } -- n := 0 -+func TestBenchmarkContext(t *testing.T) { - testing.Benchmark(func(b *testing.B) { -- // Unlike "for i := range N {...}" style loops, this -- // setup logic will only be executed once, so simpleFunc -- // will always get argument 1. -- n++ -- // It behaves just like "for i := range N {...}", except with keeping -- // function call parameters and results alive. -- for b.Loop() { -- // This function call, if was in a normal loop, will be optimized away -- // completely, first by inlining, then by dead code elimination. -- // In a b.Loop loop, the compiler ensures that this function is not optimized away. -- simpleFunc(n) -+ ctx := b.Context() -+ if err := ctx.Err(); err != nil { -+ b.Fatalf("expected non-canceled context, got %v", err) - } -- // This clean-up will only be executed once, so after the benchmark, the user -- // will see n == 2. -- n++ -- // Use b.ReportMetric as usual just like what a user may do after -- // b.N loop. -- }) -- // We can expect n == 2 here. - -- // The return value of the above Benchmark could be used just like -- // a b.N loop benchmark as well. -+ var innerCtx context.Context -+ b.Run("inner", func(b *testing.B) { -+ innerCtx = b.Context() -+ if err := innerCtx.Err(); err != nil { -+ b.Fatalf("expected inner benchmark to not inherit canceled context, got %v", err) -+ } -+ }) -+ b.Run("inner2", func(b *testing.B) { -+ if !errors.Is(innerCtx.Err(), context.Canceled) { -+ t.Fatal("expected context of sibling benchmark to be canceled after its test function finished") -+ } -+ }) -+ -+ t.Cleanup(func() { -+ if !errors.Is(ctx.Err(), context.Canceled) { -+ t.Fatal("expected context canceled before cleanup") -+ } -+ }) -+ }) - } - - func ExampleB_RunParallel() { -@@ -219,7 +197,7 @@ func ExampleB_ReportMetric() { - // specific algorithm (in this case, sorting). - testing.Benchmark(func(b *testing.B) { - var compares int64 -- for i := 0; i < b.N; i++ { -+ for b.Loop() { - s := []int{5, 4, 3, 2, 1} - slices.SortFunc(s, func(a, b int) int { - compares++ -diff --git a/src/testing/example_loop_test.go b/src/testing/example_loop_test.go -new file mode 100644 -index 0000000000..eff8bab352 ---- /dev/null -+++ b/src/testing/example_loop_test.go -@@ -0,0 +1,48 @@ -+// Copyright 2024 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package testing_test -+ -+import ( -+ "math/rand/v2" -+ "testing" -+) -+ -+// ExBenchmark shows how to use b.Loop in a benchmark. -+// -+// (If this were a real benchmark, not an example, this would be named -+// BenchmarkSomething.) -+func ExBenchmark(b *testing.B) { -+ // Generate a large random slice to use as an input. -+ // Since this is done before the first call to b.Loop(), -+ // it doesn't count toward the benchmark time. -+ input := make([]int, 128<<10) -+ for i := range input { -+ input[i] = rand.Int() -+ } -+ -+ // Perform the benchmark. -+ for b.Loop() { -+ // Normally, the compiler would be allowed to optimize away the call -+ // to sum because it has no side effects and the result isn't used. -+ // However, inside a b.Loop loop, the compiler ensures function calls -+ // aren't optimized away. -+ sum(input) -+ } -+ -+ // Outside the loop, the timer is stopped, so we could perform -+ // cleanup if necessary without affecting the result. -+} -+ -+func sum(data []int) int { -+ total := 0 -+ for _, value := range data { -+ total += value -+ } -+ return total -+} -+ -+func ExampleB_Loop() { -+ testing.Benchmark(ExBenchmark) -+} -diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go -index b41a07f88e..dceb786ae2 100644 ---- a/src/testing/fuzz.go -+++ b/src/testing/fuzz.go -@@ -5,6 +5,7 @@ - package testing - - import ( -+ "context" - "errors" - "flag" - "fmt" -@@ -293,6 +294,8 @@ func (f *F) Fuzz(ff any) { - f.tstate.match.clearSubNames() - } - -+ ctx, cancelCtx := context.WithCancel(f.ctx) -+ - // Record the stack trace at the point of this call so that if the subtest - // function - which runs in a separate stack - is marked as a helper, we can - // continue walking the stack into the parent test. -@@ -300,13 +303,15 @@ func (f *F) Fuzz(ff any) { - n := runtime.Callers(2, pc[:]) - t := &T{ - common: common{ -- barrier: make(chan bool), -- signal: make(chan bool), -- name: testName, -- parent: &f.common, -- level: f.level + 1, -- creator: pc[:n], -- chatty: f.chatty, -+ barrier: make(chan bool), -+ signal: make(chan bool), -+ name: testName, -+ parent: &f.common, -+ level: f.level + 1, -+ creator: pc[:n], -+ chatty: f.chatty, -+ ctx: ctx, -+ cancelCtx: cancelCtx, - }, - tstate: f.tstate, - } -@@ -508,14 +513,17 @@ func runFuzzTests(deps testDeps, fuzzTests []InternalFuzzTarget, deadline time.T - continue - } - } -+ ctx, cancelCtx := context.WithCancel(context.Background()) - f := &F{ - common: common{ -- signal: make(chan bool), -- barrier: make(chan bool), -- name: testName, -- parent: &root, -- level: root.level + 1, -- chatty: root.chatty, -+ signal: make(chan bool), -+ barrier: make(chan bool), -+ name: testName, -+ parent: &root, -+ level: root.level + 1, -+ chatty: root.chatty, -+ ctx: ctx, -+ cancelCtx: cancelCtx, - }, - tstate: tstate, - fstate: fstate, -@@ -590,14 +598,17 @@ func runFuzzing(deps testDeps, fuzzTests []InternalFuzzTarget) (ok bool) { - return false - } - -+ ctx, cancelCtx := context.WithCancel(context.Background()) - f := &F{ - common: common{ -- signal: make(chan bool), -- barrier: nil, // T.Parallel has no effect when fuzzing. -- name: testName, -- parent: &root, -- level: root.level + 1, -- chatty: root.chatty, -+ signal: make(chan bool), -+ barrier: nil, // T.Parallel has no effect when fuzzing. -+ name: testName, -+ parent: &root, -+ level: root.level + 1, -+ chatty: root.chatty, -+ ctx: ctx, -+ cancelCtx: cancelCtx, - }, - fstate: fstate, - tstate: tstate, -diff --git a/src/testing/loop_test.go b/src/testing/loop_test.go -new file mode 100644 -index 0000000000..7a1a93fcee ---- /dev/null -+++ b/src/testing/loop_test.go -@@ -0,0 +1,57 @@ -+// Copyright 2024 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package testing -+ -+func TestBenchmarkBLoop(t *T) { -+ var initialStart highPrecisionTime -+ var firstStart highPrecisionTime -+ var lastStart highPrecisionTime -+ var runningEnd bool -+ runs := 0 -+ iters := 0 -+ finalBN := 0 -+ bRet := Benchmark(func(b *B) { -+ initialStart = b.start -+ runs++ -+ for b.Loop() { -+ if iters == 0 { -+ firstStart = b.start -+ } -+ lastStart = b.start -+ iters++ -+ } -+ finalBN = b.N -+ runningEnd = b.timerOn -+ }) -+ // Verify that a b.Loop benchmark is invoked just once. -+ if runs != 1 { -+ t.Errorf("want runs == 1, got %d", runs) -+ } -+ // Verify that at least one iteration ran. -+ if iters == 0 { -+ t.Fatalf("no iterations ran") -+ } -+ // Verify that b.N, bRet.N, and the b.Loop() iteration count match. -+ if finalBN != iters || bRet.N != iters { -+ t.Errorf("benchmark iterations mismatch: %d loop iterations, final b.N=%d, bRet.N=%d", iters, finalBN, bRet.N) -+ } -+ // Make sure the benchmark ran for an appropriate amount of time. -+ if bRet.T < benchTime.d { -+ t.Fatalf("benchmark ran for %s, want >= %s", bRet.T, benchTime.d) -+ } -+ // Verify that the timer is reset on the first loop, and then left alone. -+ if firstStart == initialStart { -+ t.Errorf("b.Loop did not reset the timer") -+ } -+ if lastStart != firstStart { -+ t.Errorf("timer was reset during iteration") -+ } -+ // Verify that it stopped the timer after the last loop. -+ if runningEnd { -+ t.Errorf("timer was still running after last iteration") -+ } -+} -+ -+// See also TestBenchmarkBLoop* in other files. -diff --git a/src/testing/synctest/context_example_test.go b/src/testing/synctest/context_example_test.go -new file mode 100644 -index 0000000000..5f7205e50e ---- /dev/null -+++ b/src/testing/synctest/context_example_test.go -@@ -0,0 +1,78 @@ -+// Copyright 2025 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+//go:build goexperiment.synctest -+ -+package synctest_test -+ -+import ( -+ "context" -+ "fmt" -+ "testing/synctest" -+ "time" -+) -+ -+// This example demonstrates testing the context.AfterFunc function. -+// -+// AfterFunc registers a function to execute in a new goroutine -+// after a context is canceled. -+// -+// The test verifies that the function is not run before the context is canceled, -+// and is run after the context is canceled. -+func Example_contextAfterFunc() { -+ synctest.Run(func() { -+ // Create a context.Context which can be canceled. -+ ctx, cancel := context.WithCancel(context.Background()) -+ -+ // context.AfterFunc registers a function to be called -+ // when a context is canceled. -+ afterFuncCalled := false -+ context.AfterFunc(ctx, func() { -+ afterFuncCalled = true -+ }) -+ -+ // The context has not been canceled, so the AfterFunc is not called. -+ synctest.Wait() -+ fmt.Printf("before context is canceled: afterFuncCalled=%v\n", afterFuncCalled) -+ -+ // Cancel the context and wait for the AfterFunc to finish executing. -+ // Verify that the AfterFunc ran. -+ cancel() -+ synctest.Wait() -+ fmt.Printf("after context is canceled: afterFuncCalled=%v\n", afterFuncCalled) -+ -+ // Output: -+ // before context is canceled: afterFuncCalled=false -+ // after context is canceled: afterFuncCalled=true -+ }) -+} -+ -+// This example demonstrates testing the context.WithTimeout function. -+// -+// WithTimeout creates a context which is canceled after a timeout. -+// -+// The test verifies that the context is not canceled before the timeout expires, -+// and is canceled after the timeout expires. -+func Example_contextWithTimeout() { -+ synctest.Run(func() { -+ // Create a context.Context which is canceled after a timeout. -+ const timeout = 5 * time.Second -+ ctx, cancel := context.WithTimeout(context.Background(), timeout) -+ defer cancel() -+ -+ // Wait just less than the timeout. -+ time.Sleep(timeout - time.Nanosecond) -+ synctest.Wait() -+ fmt.Printf("before timeout: ctx.Err() = %v\n", ctx.Err()) -+ -+ // Wait the rest of the way until the timeout. -+ time.Sleep(time.Nanosecond) -+ synctest.Wait() -+ fmt.Printf("after timeout: ctx.Err() = %v\n", ctx.Err()) -+ -+ // Output: -+ // before timeout: ctx.Err() = -+ // after timeout: ctx.Err() = context deadline exceeded -+ }) -+} -diff --git a/src/testing/testing.go b/src/testing/testing.go -index e353ceb741..be6391b0ab 100644 ---- a/src/testing/testing.go -+++ b/src/testing/testing.go -@@ -72,27 +72,24 @@ - // A sample benchmark function looks like this: - // - // func BenchmarkRandInt(b *testing.B) { --// for range b.N { -+// for b.Loop() { - // rand.Int() - // } - // } - // --// The benchmark function must run the target code b.N times. --// It is called multiple times with b.N adjusted until the --// benchmark function lasts long enough to be timed reliably. - // The output - // - // BenchmarkRandInt-8 68453040 17.8 ns/op - // --// means that the loop ran 68453040 times at a speed of 17.8 ns per loop. -+// means that the body of the loop ran 68453040 times at a speed of 17.8 ns per loop. - // --// If a benchmark needs some expensive setup before running, the timer --// may be reset: -+// Only the body of the loop is timed, so benchmarks may do expensive -+// setup before calling b.Loop, which will not be counted toward the -+// benchmark measurement: - // - // func BenchmarkBigLen(b *testing.B) { - // big := NewBig() --// b.ResetTimer() --// for range b.N { -+// for b.Loop() { - // big.Len() - // } - // } -@@ -120,6 +117,37 @@ - // In particular, https://golang.org/x/perf/cmd/benchstat performs - // statistically robust A/B comparisons. - // -+// # b.N-style benchmarks -+// -+// Prior to the introduction of [B.Loop], benchmarks were written in a -+// different style using [B.N]. For example: -+// -+// func BenchmarkRandInt(b *testing.B) { -+// for range b.N { -+// rand.Int() -+// } -+// } -+// -+// In this style of benchmark, the benchmark function must run -+// the target code b.N times. The benchmark function is called -+// multiple times with b.N adjusted until the benchmark function -+// lasts long enough to be timed reliably. This also means any setup -+// done before the loop may be run several times. -+// -+// If a benchmark needs some expensive setup before running, the timer -+// should be explicitly reset: -+// -+// func BenchmarkBigLen(b *testing.B) { -+// big := NewBig() -+// b.ResetTimer() -+// for range b.N { -+// big.Len() -+// } -+// } -+// -+// New benchmarks should prefer using [B.Loop], which is more robust -+// and more efficient. -+// - // # Examples - // - // The package also runs and verifies example code. Example functions may -@@ -1357,10 +1385,10 @@ func (c *common) Chdir(dir string) { - } - - // Context returns a context that is canceled just before --// [T.Cleanup]-registered functions are called. -+// Cleanup-registered functions are called. - // - // Cleanup functions can wait for any resources --// that shut down on Context.Done before the test completes. -+// that shut down on Context.Done before the test or benchmark completes. - func (c *common) Context() context.Context { - c.checkFuzzFn("Context") - return c.ctx -diff --git a/src/unique/handle.go b/src/unique/handle.go -index 46f2da3ddc..520ab70f8c 100644 ---- a/src/unique/handle.go -+++ b/src/unique/handle.go -@@ -89,7 +89,7 @@ func Make[T comparable](value T) Handle[T] { - } - - var ( -- // uniqueMaps is an index of type-specific sync maps used for unique.Make. -+ // uniqueMaps is an index of type-specific concurrent maps used for unique.Make. - // - // The two-level map might seem odd at first since the HashTrieMap could have "any" - // as its key type, but the issue is escape analysis. We do not want to force lookups -diff --git a/src/weak/pointer.go b/src/weak/pointer.go -index fb10bc2d69..39c512e76d 100644 ---- a/src/weak/pointer.go -+++ b/src/weak/pointer.go -@@ -13,9 +13,9 @@ import ( - // Pointer is a weak pointer to a value of type T. - // - // Just like regular pointers, Pointer may reference any part of an --// object, such as the field of a struct or an element of an array. -+// object, such as a field of a struct or an element of an array. - // Objects that are only pointed to by weak pointers are not considered --// reachable and once the object becomes unreachable [Pointer.Value] -+// reachable, and once the object becomes unreachable, [Pointer.Value] - // may return nil. - // - // The primary use-cases for weak pointers are for implementing caches, -@@ -23,19 +23,19 @@ import ( - // the lifetimes of separate values (for example, through a map with weak - // keys). - // --// Two Pointer values always compare equal if the pointers that they were --// created from compare equal. This property is retained even after the -+// Two Pointer values always compare equal if the pointers from which they were -+// created compare equal. This property is retained even after the - // object referenced by the pointer used to create a weak reference is - // reclaimed. --// If multiple weak pointers are made to different offsets within same object -+// If multiple weak pointers are made to different offsets within the same object - // (for example, pointers to different fields of the same struct), those pointers - // will not compare equal. - // If a weak pointer is created from an object that becomes unreachable, but is - // then resurrected due to a finalizer, that weak pointer will not compare equal --// with weak pointers created after resurrection. -+// with weak pointers created after the resurrection. - // - // Calling [Make] with a nil pointer returns a weak pointer whose [Pointer.Value] --// always returns nil. The zero value of a Pointer behaves as if it was created -+// always returns nil. The zero value of a Pointer behaves as if it were created - // by passing nil to [Make] and compares equal with such pointers. - // - // [Pointer.Value] is not guaranteed to eventually return nil. -@@ -52,7 +52,7 @@ import ( - // nil, even after an object is no longer referenced, the runtime is allowed to - // perform a space-saving optimization that batches objects together in a single - // allocation slot. The weak pointer for an unreferenced object in such an --// allocation may never be called if it always exists in the same batch as a -+// allocation may never become nil if it always exists in the same batch as a - // referenced object. Typically, this batching only happens for tiny - // (on the order of 16 bytes or less) and pointer-free objects. - type Pointer[T any] struct { -@@ -78,6 +78,9 @@ func Make[T any](ptr *T) Pointer[T] { - // If a weak pointer points to an object with a finalizer, then Value will - // return nil as soon as the object's finalizer is queued for execution. - func (p Pointer[T]) Value() *T { -+ if p.u == nil { -+ return nil -+ } - return (*T)(runtime_makeStrongFromWeak(p.u)) - } - -diff --git a/src/weak/pointer_test.go b/src/weak/pointer_test.go -index 002b4130f0..e0ef30377e 100644 ---- a/src/weak/pointer_test.go -+++ b/src/weak/pointer_test.go -@@ -21,6 +21,15 @@ type T struct { - } - - func TestPointer(t *testing.T) { -+ var zero weak.Pointer[T] -+ if zero.Value() != nil { -+ t.Error("Value of zero value of weak.Pointer is not nil") -+ } -+ zeroNil := weak.Make[T](nil) -+ if zeroNil.Value() != nil { -+ t.Error("Value of weak.Make[T](nil) is not nil") -+ } -+ - bt := new(T) - wt := weak.Make(bt) - if st := wt.Value(); st != bt { -@@ -41,6 +50,12 @@ func TestPointer(t *testing.T) { - } - - func TestPointerEquality(t *testing.T) { -+ var zero weak.Pointer[T] -+ zeroNil := weak.Make[T](nil) -+ if zero != zeroNil { -+ t.Error("weak.Make[T](nil) != zero value of weak.Pointer[T]") -+ } -+ - bt := make([]*T, 10) - wt := make([]weak.Pointer[T], 10) - wo := make([]weak.Pointer[int], 10) diff --git a/golang.spec b/golang.spec index bccc07f..80b482a 100644 --- a/golang.spec +++ b/golang.spec @@ -100,7 +100,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.24 -%global go_prerelease rc1 +%global go_prerelease rc2 #global go_patch 4 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} @@ -157,10 +157,6 @@ Requires: go-filesystem Patch1: 0001-Modify-go.env.patch Patch5: 0005-Skip-TestCrashDumpsAllThreads.patch Patch6: 0006-Default-to-ld.bfd-on-ARM64.patch -# This is a huge patch. At the time of the Fedora merge, there was no rc2 tag -# to include a significant amount of necessary changes so I generated a single patch -# git diff go1.24rc1..release-branch.go1.24 > combined_commits_2025-01-08.patch -Patch7: combined_commits_2025-01-08.patch # Related to https://gcc.gnu.org/PR118497 Patch8: fix_cgo_panic-with-gcc15-in-368.patch diff --git a/sources b/sources index a426d66..203dff8 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.24rc1.src.tar.gz) = f37b24f9964a7f6580ca0ecb1c4d197d8053429753b1b559dae0d66041c7274a3981daae5dddf93677e23a20dcf5cbdc4b70fbc772df46a611f6a063af3d3d64 +SHA512 (go1.24rc2.src.tar.gz) = 767c5c030a3fd84be7c449d431148df5da5fb5cf3d19886e238ea1c535a36f25b3a3433dfc690ef0dac2fc4e9fc9f899bc748494bc1339710267ba02de178676 From 38634fa1232d6a4b86a63b4fcb39e6960d8cee72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Thu, 6 Feb 2025 09:21:54 +0100 Subject: [PATCH 44/75] Remove F39, is EOL --- .packit.yaml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.packit.yaml b/.packit.yaml index eebf294..9b03fd4 100644 --- a/.packit.yaml +++ b/.packit.yaml @@ -12,13 +12,6 @@ actions: - bash -c "echo - New release ${PACKIT_PROJECT_VERSION}" jobs: - # Fedora 39 follows Go 1.22 - # https://pagure.io/fesco/issue/3261 - - job: pull_from_upstream - trigger: release - dist_git_branches: fedora-39 - upstream_tag_include: "^go1.22.+" - # Fedora 40 follows Go 1.22 - job: pull_from_upstream trigger: release From a5f7a9b770246790149f76fb06c73950326a25f2 Mon Sep 17 00:00:00 2001 From: Packit Date: Wed, 5 Feb 2025 20:59:25 +0000 Subject: [PATCH 45/75] Update to 1.24rc3 upstream release Upstream tag: go1.24rc3 Upstream commit: 18068cb9 Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + README.packit | 2 +- golang.spec | 6 +++--- sources | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 5541ed2..1a608c2 100644 --- a/.gitignore +++ b/.gitignore @@ -159,3 +159,4 @@ /go1.23.4.src.tar.gz /go1.24rc1.src.tar.gz /go1.24rc2.src.tar.gz +/go1.24rc3.src.tar.gz diff --git a/README.packit b/README.packit index 13501e1..c1b4159 100644 --- a/README.packit +++ b/README.packit @@ -1,3 +1,3 @@ This repository is maintained by packit. https://packit.dev/ -The file was generated using packit 0.104.1.post1.dev2+g8a1a06eb. +The file was generated using packit 1.1.0. diff --git a/golang.spec b/golang.spec index 80b482a..e20bd3e 100644 --- a/golang.spec +++ b/golang.spec @@ -99,9 +99,9 @@ %endif # Comment out go_prerelease and go_patch as needed -%global go_api 1.24 -%global go_prerelease rc2 -#global go_patch 4 +%global go_api 1 +%global go_prerelease rc3 +%global go_patch 24 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index 203dff8..86f7c46 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.24rc2.src.tar.gz) = 767c5c030a3fd84be7c449d431148df5da5fb5cf3d19886e238ea1c535a36f25b3a3433dfc690ef0dac2fc4e9fc9f899bc748494bc1339710267ba02de178676 +SHA512 (go1.24rc3.src.tar.gz) = becb7cb54515553360b4c4232298ec5f6c0ad176ac1044810e8239d00bf23ae3b61dae1af4fdb1f4b73d9fc194c18e4399dcc19301093eacf69af7adffc78159 From 9fdfa10de721f708501fb018db39061a458f3a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Thu, 6 Feb 2025 08:59:12 +0100 Subject: [PATCH 46/75] Fix tags --- golang.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/golang.spec b/golang.spec index e20bd3e..9f002e8 100644 --- a/golang.spec +++ b/golang.spec @@ -99,9 +99,9 @@ %endif # Comment out go_prerelease and go_patch as needed -%global go_api 1 +%global go_api 1.24 %global go_prerelease rc3 -%global go_patch 24 +#global go_patch 4 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} From d02739b52d95efe8dec2dd61e23a7b60cfe568d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Fri, 14 Feb 2025 10:33:19 +0100 Subject: [PATCH 47/75] Update to 1.24.0 Resolves: rhbz#2344988 --- .gitignore | 1 + golang.spec | 8 ++++---- sources | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 1a608c2..9adc181 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,4 @@ /go1.24rc1.src.tar.gz /go1.24rc2.src.tar.gz /go1.24rc3.src.tar.gz +/go1.24.0.src.tar.gz diff --git a/golang.spec b/golang.spec index 9f002e8..865d9be 100644 --- a/golang.spec +++ b/golang.spec @@ -100,8 +100,8 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.24 -%global go_prerelease rc3 -#global go_patch 4 +#global go_prerelease rc3 +%global go_patch 0 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} @@ -141,13 +141,13 @@ Provides: bundled(golang(golang.org/x/arch)) = 0.12.0 Provides: bundled(golang(golang.org/x/build)) = 0.0.0.20241205234318.b850320af2a4 Provides: bundled(golang(golang.org/x/crypto)) = 0.30.0 Provides: bundled(golang(golang.org/x/mod)) = 0.22.0 -Provides: bundled(golang(golang.org/x/net)) = 0.32.1.0.20241206180132.552d8ac903a1 +Provides: bundled(golang(golang.org/x/net)) = 0.32.1.0.20250121202134.9a960c88dd98 Provides: bundled(golang(golang.org/x/sync)) = 0.10.0 Provides: bundled(golang(golang.org/x/sys)) = 0.28.0 Provides: bundled(golang(golang.org/x/telemetry)) = 0.0.0.20241204182053.c0ac0e154df3 Provides: bundled(golang(golang.org/x/term)) = 0.27.0 Provides: bundled(golang(golang.org/x/text)) = 0.21.0 -Provides: bundled(golang(golang.org/x/tools)) = 0.28.0 +Provides: bundled(golang(golang.org/x/tools)) = 0.28.1.0.20250131145412.98746475647e Provides: bundled(golang(rsc.io/markdown)) = 0.0.0.20240306144322.0bf8f97ee8ef Requires: %{name}-bin = %{version}-%{release} diff --git a/sources b/sources index 86f7c46..34c4391 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.24rc3.src.tar.gz) = becb7cb54515553360b4c4232298ec5f6c0ad176ac1044810e8239d00bf23ae3b61dae1af4fdb1f4b73d9fc194c18e4399dcc19301093eacf69af7adffc78159 +SHA512 (go1.24.0.src.tar.gz) = 36ba9a3a541208fd33aa49b969d892578e209570541d2b6ca6ff784250d8b6777597d347b823c6026acf0c2741b4abc9012693004e623a1434b06cfecdbebaa8 From bfa1718f05c9e69f019d49563ad189b2a6bf81c2 Mon Sep 17 00:00:00 2001 From: Packit Date: Thu, 6 Mar 2025 10:38:53 +0000 Subject: [PATCH 48/75] Update to 1.24.1 upstream release - Resolves: rhbz#2344988 Upstream tag: go1.24.1 Upstream commit: 339c903a Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + README.packit | 2 +- golang.spec | 2 +- sources | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 9adc181..5bc581b 100644 --- a/.gitignore +++ b/.gitignore @@ -161,3 +161,4 @@ /go1.24rc2.src.tar.gz /go1.24rc3.src.tar.gz /go1.24.0.src.tar.gz +/go1.24.1.src.tar.gz diff --git a/README.packit b/README.packit index c1b4159..87210c5 100644 --- a/README.packit +++ b/README.packit @@ -1,3 +1,3 @@ This repository is maintained by packit. https://packit.dev/ -The file was generated using packit 1.1.0. +The file was generated using packit 1.2.0.post1.dev3+g3adf9afe. diff --git a/golang.spec b/golang.spec index 865d9be..01f5d3b 100644 --- a/golang.spec +++ b/golang.spec @@ -101,7 +101,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.24 #global go_prerelease rc3 -%global go_patch 0 +%global go_patch 1 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index 34c4391..993c1a8 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.24.0.src.tar.gz) = 36ba9a3a541208fd33aa49b969d892578e209570541d2b6ca6ff784250d8b6777597d347b823c6026acf0c2741b4abc9012693004e623a1434b06cfecdbebaa8 +SHA512 (go1.24.1.src.tar.gz) = a924d6bdc7e7101917e6d063bc7b471390525394e79224c152997564657c4362b5600e0c8bf6ee857d345129ccf7368bdf4ed2251ab740446ea2abda144e6353 From 6483580d3fe82fad359ccfb9a8e6f40aa11e5308 Mon Sep 17 00:00:00 2001 From: Packit Date: Tue, 1 Apr 2025 18:03:11 +0000 Subject: [PATCH 49/75] Update to 1.24.2 upstream release - Resolves: rhbz#2356701 Upstream tag: go1.24.2 Upstream commit: 49860cf9 Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + README.packit | 2 +- golang.spec | 2 +- sources | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 5bc581b..5a488dd 100644 --- a/.gitignore +++ b/.gitignore @@ -162,3 +162,4 @@ /go1.24rc3.src.tar.gz /go1.24.0.src.tar.gz /go1.24.1.src.tar.gz +/go1.24.2.src.tar.gz diff --git a/README.packit b/README.packit index 87210c5..bb4a369 100644 --- a/README.packit +++ b/README.packit @@ -1,3 +1,3 @@ This repository is maintained by packit. https://packit.dev/ -The file was generated using packit 1.2.0.post1.dev3+g3adf9afe. +The file was generated using packit 1.4.0.post1.dev4+g043c5fde. diff --git a/golang.spec b/golang.spec index 01f5d3b..1738f94 100644 --- a/golang.spec +++ b/golang.spec @@ -101,7 +101,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.24 #global go_prerelease rc3 -%global go_patch 1 +%global go_patch 2 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index 993c1a8..5e215de 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.24.1.src.tar.gz) = a924d6bdc7e7101917e6d063bc7b471390525394e79224c152997564657c4362b5600e0c8bf6ee857d345129ccf7368bdf4ed2251ab740446ea2abda144e6353 +SHA512 (go1.24.2.src.tar.gz) = 6366a32f6678e7908b138f62dafeed96f7144b3b93505e75fba374b33727da8b1d087c1f979f493382b319758ebfcbeb30e9d7dadcb2923b628c8abe7db41c6f From ac1089821f8417c80ecd521251a758a654459b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Mon, 14 Apr 2025 12:23:00 +0200 Subject: [PATCH 50/75] Fedora 40 now follows Go 1.23 Reference: https://pagure.io/fesco/issue/3372 --- .packit.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.packit.yaml b/.packit.yaml index 9b03fd4..f12f73e 100644 --- a/.packit.yaml +++ b/.packit.yaml @@ -12,11 +12,12 @@ actions: - bash -c "echo - New release ${PACKIT_PROJECT_VERSION}" jobs: - # Fedora 40 follows Go 1.22 + # Fedora 40 follows Go 1.23 + # https://pagure.io/fesco/issue/3372 - job: pull_from_upstream trigger: release dist_git_branches: fedora-40 - upstream_tag_include: "^go1.22.+" + upstream_tag_include: "^go1.23.+" # Fedora 41 follows Go 1.23 - job: pull_from_upstream From 782a5318128373eddf80085ee2898a4dd9eb5654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Tue, 22 Apr 2025 17:26:28 +0200 Subject: [PATCH 51/75] Backport of upstream issue 73144 --- ff2636f.patch | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++ golang.spec | 9 +- 2 files changed, 240 insertions(+), 3 deletions(-) create mode 100644 ff2636f.patch diff --git a/ff2636f.patch b/ff2636f.patch new file mode 100644 index 0000000..5baed13 --- /dev/null +++ b/ff2636f.patch @@ -0,0 +1,234 @@ +From ff2636f45e0087a1c6d8e895257d9c4729710811 Mon Sep 17 00:00:00 2001 +From: Michael Pratt +Date: Thu, 03 Apr 2025 03:26:25 +0000 +Subject: [PATCH] [release-branch.go1.24] runtime: cleanup M vgetrandom state before dropping P + +When an M is destroyed, we put its vgetrandom state back on the shared +list for another M to reuse. This list is simply a slice, so appending +to the slice may allocate. Currently this operation is performed in +mdestroy, after the P is released, meaning allocation is not allowed. + +More the cleanup earlier in mdestroy when allocation is still OK. + +Also add //go:nowritebarrierrec to mdestroy since it runs without a P, +which would have caught this bug. + +Fixes #73144. +For #73141. + +Change-Id: I6a6a636c3fbf5c6eec09d07a260e39dbb4d2db12 +Reviewed-on: https://go-review.googlesource.com/c/go/+/662455 +Reviewed-by: Jason Donenfeld +LUCI-TryBot-Result: Go LUCI +Reviewed-by: Keith Randall +Reviewed-by: Keith Randall +(cherry picked from commit 0b31e6d4cc804ab76ae8ced151ee2f50657aec14) +--- + +diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go +index cf163a6..ded821b 100644 +--- a/src/runtime/os3_solaris.go ++++ b/src/runtime/os3_solaris.go +@@ -234,8 +234,11 @@ + getg().m.procid = 0 + } + +-// Called from exitm, but not from drop, to undo the effect of thread-owned ++// Called from mexit, but not from dropm, to undo the effect of thread-owned + // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. ++// ++// This always runs without a P, so //go:nowritebarrierrec is required. ++//go:nowritebarrierrec + func mdestroy(mp *m) { + } + +diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go +index 93464cb..1b483c2 100644 +--- a/src/runtime/os_aix.go ++++ b/src/runtime/os_aix.go +@@ -186,8 +186,11 @@ + getg().m.procid = 0 + } + +-// Called from exitm, but not from drop, to undo the effect of thread-owned ++// Called from mexit, but not from dropm, to undo the effect of thread-owned + // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. ++// ++// This always runs without a P, so //go:nowritebarrierrec is required. ++//go:nowritebarrierrec + func mdestroy(mp *m) { + } + +diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go +index 0ecbea7..6eab3b5 100644 +--- a/src/runtime/os_darwin.go ++++ b/src/runtime/os_darwin.go +@@ -344,8 +344,11 @@ + getg().m.procid = 0 + } + +-// Called from exitm, but not from drop, to undo the effect of thread-owned ++// Called from mexit, but not from dropm, to undo the effect of thread-owned + // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. ++// ++// This always runs without a P, so //go:nowritebarrierrec is required. ++//go:nowritebarrierrec + func mdestroy(mp *m) { + } + +diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go +index a02696e..9b32350 100644 +--- a/src/runtime/os_dragonfly.go ++++ b/src/runtime/os_dragonfly.go +@@ -216,8 +216,11 @@ + getg().m.procid = 0 + } + +-// Called from exitm, but not from drop, to undo the effect of thread-owned ++// Called from mexit, but not from dropm, to undo the effect of thread-owned + // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. ++// ++// This always runs without a P, so //go:nowritebarrierrec is required. ++//go:nowritebarrierrec + func mdestroy(mp *m) { + } + +diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go +index 8b3c4d0..fb46b81 100644 +--- a/src/runtime/os_linux.go ++++ b/src/runtime/os_linux.go +@@ -412,13 +412,12 @@ + getg().m.procid = 0 + } + +-// Called from exitm, but not from drop, to undo the effect of thread-owned ++// Called from mexit, but not from dropm, to undo the effect of thread-owned + // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. ++// ++// This always runs without a P, so //go:nowritebarrierrec is required. ++//go:nowritebarrierrec + func mdestroy(mp *m) { +- if mp.vgetrandomState != 0 { +- vgetrandomPutState(mp.vgetrandomState) +- mp.vgetrandomState = 0 +- } + } + + // #ifdef GOARCH_386 +diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go +index 735ace2..a06e5fe 100644 +--- a/src/runtime/os_netbsd.go ++++ b/src/runtime/os_netbsd.go +@@ -320,8 +320,11 @@ + // must continue working after unminit. + } + +-// Called from exitm, but not from drop, to undo the effect of thread-owned ++// Called from mexit, but not from dropm, to undo the effect of thread-owned + // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. ++// ++// This always runs without a P, so //go:nowritebarrierrec is required. ++//go:nowritebarrierrec + func mdestroy(mp *m) { + } + +diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go +index 574bfa8..4ce4c3c 100644 +--- a/src/runtime/os_openbsd.go ++++ b/src/runtime/os_openbsd.go +@@ -182,8 +182,11 @@ + getg().m.procid = 0 + } + +-// Called from exitm, but not from drop, to undo the effect of thread-owned ++// Called from mexit, but not from dropm, to undo the effect of thread-owned + // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. ++// ++// This always runs without a P, so //go:nowritebarrierrec is required. ++//go:nowritebarrierrec + func mdestroy(mp *m) { + } + +diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go +index 2dbb42a..3b5965a 100644 +--- a/src/runtime/os_plan9.go ++++ b/src/runtime/os_plan9.go +@@ -217,8 +217,11 @@ + func unminit() { + } + +-// Called from exitm, but not from drop, to undo the effect of thread-owned ++// Called from mexit, but not from dropm, to undo the effect of thread-owned + // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. ++// ++// This always runs without a P, so //go:nowritebarrierrec is required. ++//go:nowritebarrierrec + func mdestroy(mp *m) { + } + +diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go +index 7183e79..54407a3 100644 +--- a/src/runtime/os_windows.go ++++ b/src/runtime/os_windows.go +@@ -906,9 +906,11 @@ + mp.procid = 0 + } + +-// Called from exitm, but not from drop, to undo the effect of thread-owned ++// Called from mexit, but not from dropm, to undo the effect of thread-owned + // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. + // ++// This always runs without a P, so //go:nowritebarrierrec is required. ++//go:nowritebarrierrec + //go:nosplit + func mdestroy(mp *m) { + if mp.highResTimer != 0 { +diff --git a/src/runtime/proc.go b/src/runtime/proc.go +index e9873e5..21bee4d 100644 +--- a/src/runtime/proc.go ++++ b/src/runtime/proc.go +@@ -1935,6 +1935,9 @@ + mp.gsignal = nil + } + ++ // Free vgetrandom state. ++ vgetrandomDestroy(mp) ++ + // Remove m from allm. + lock(&sched.lock) + for pprev := &allm; *pprev != nil; pprev = &(*pprev).alllink { +diff --git a/src/runtime/vgetrandom_linux.go b/src/runtime/vgetrandom_linux.go +index a6ec4b7..40be022 100644 +--- a/src/runtime/vgetrandom_linux.go ++++ b/src/runtime/vgetrandom_linux.go +@@ -73,9 +73,16 @@ + return state + } + +-func vgetrandomPutState(state uintptr) { ++// Free vgetrandom state from the M (if any) prior to destroying the M. ++// ++// This may allocate, so it must have a P. ++func vgetrandomDestroy(mp *m) { ++ if mp.vgetrandomState == 0 { ++ return ++ } ++ + lock(&vgetrandomAlloc.statesLock) +- vgetrandomAlloc.states = append(vgetrandomAlloc.states, state) ++ vgetrandomAlloc.states = append(vgetrandomAlloc.states, mp.vgetrandomState) + unlock(&vgetrandomAlloc.statesLock) + } + +diff --git a/src/runtime/vgetrandom_unsupported.go b/src/runtime/vgetrandom_unsupported.go +index 070392c..43c53e1 100644 +--- a/src/runtime/vgetrandom_unsupported.go ++++ b/src/runtime/vgetrandom_unsupported.go +@@ -13,6 +13,6 @@ + return -1, false + } + +-func vgetrandomPutState(state uintptr) {} ++func vgetrandomDestroy(mp *m) {} + + func vgetrandomInit() {} diff --git a/golang.spec b/golang.spec index 1738f94..ad9331b 100644 --- a/golang.spec +++ b/golang.spec @@ -155,10 +155,13 @@ Requires: %{name}-src = %{version}-%{release} Requires: go-filesystem Patch1: 0001-Modify-go.env.patch -Patch5: 0005-Skip-TestCrashDumpsAllThreads.patch -Patch6: 0006-Default-to-ld.bfd-on-ARM64.patch +Patch5: 0005-Skip-TestCrashDumpsAllThreads.patch +Patch6: 0006-Default-to-ld.bfd-on-ARM64.patch # Related to https://gcc.gnu.org/PR118497 -Patch8: fix_cgo_panic-with-gcc15-in-368.patch +Patch8: fix_cgo_panic-with-gcc15-in-368.patch + +# Remove with Go 1.24.3 +Patch9: ff2636f.patch # Having documentation separate was broken Obsoletes: %{name}-docs < 1.1-4 From ad2442f5a0b4fae569e791d19bc3a47167d69728 Mon Sep 17 00:00:00 2001 From: Packit Date: Wed, 7 May 2025 07:26:47 +0000 Subject: [PATCH 52/75] Update to 1.24.3 upstream release - Resolves: rhbz#2364602 Upstream tag: go1.24.3 Upstream commit: 34c8b14c Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + README.packit | 2 +- golang.spec | 2 +- sources | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 5a488dd..c2b1923 100644 --- a/.gitignore +++ b/.gitignore @@ -163,3 +163,4 @@ /go1.24.0.src.tar.gz /go1.24.1.src.tar.gz /go1.24.2.src.tar.gz +/go1.24.3.src.tar.gz diff --git a/README.packit b/README.packit index bb4a369..807ffc6 100644 --- a/README.packit +++ b/README.packit @@ -1,3 +1,3 @@ This repository is maintained by packit. https://packit.dev/ -The file was generated using packit 1.4.0.post1.dev4+g043c5fde. +The file was generated using packit 1.6.0.post1.dev2+gd5a7662a. diff --git a/golang.spec b/golang.spec index ad9331b..7a2849c 100644 --- a/golang.spec +++ b/golang.spec @@ -101,7 +101,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.24 #global go_prerelease rc3 -%global go_patch 2 +%global go_patch 3 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index 5e215de..0e29767 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.24.2.src.tar.gz) = 6366a32f6678e7908b138f62dafeed96f7144b3b93505e75fba374b33727da8b1d087c1f979f493382b319758ebfcbeb30e9d7dadcb2923b628c8abe7db41c6f +SHA512 (go1.24.3.src.tar.gz) = 05d19372fb923eeea19395b4de569d2ecfec7fadf2d8236d47cd667982de51c569e9816372cb79e32166553f9bcbe68f7bc2a6ded5655809b1caf5bd941011e7 From 9be033775ae9656e0011009e9f4bcc8803a98f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Wed, 7 May 2025 09:32:09 +0200 Subject: [PATCH 53/75] Remove patch --- golang.spec | 3 --- 1 file changed, 3 deletions(-) diff --git a/golang.spec b/golang.spec index 7a2849c..183d12b 100644 --- a/golang.spec +++ b/golang.spec @@ -160,9 +160,6 @@ Patch6: 0006-Default-to-ld.bfd-on-ARM64.patch # Related to https://gcc.gnu.org/PR118497 Patch8: fix_cgo_panic-with-gcc15-in-368.patch -# Remove with Go 1.24.3 -Patch9: ff2636f.patch - # Having documentation separate was broken Obsoletes: %{name}-docs < 1.1-4 From fe8033479fa13fa7f88a630577cafe0d03773b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Thu, 8 May 2025 10:53:30 +0200 Subject: [PATCH 54/75] Update bundled dependencies --- golang.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/golang.spec b/golang.spec index 183d12b..f01d3a4 100644 --- a/golang.spec +++ b/golang.spec @@ -141,7 +141,7 @@ Provides: bundled(golang(golang.org/x/arch)) = 0.12.0 Provides: bundled(golang(golang.org/x/build)) = 0.0.0.20241205234318.b850320af2a4 Provides: bundled(golang(golang.org/x/crypto)) = 0.30.0 Provides: bundled(golang(golang.org/x/mod)) = 0.22.0 -Provides: bundled(golang(golang.org/x/net)) = 0.32.1.0.20250121202134.9a960c88dd98 +Provides: bundled(golang(golang.org/x/net)) = 0.32.1.0.20250304185419.76f9bf3279ef Provides: bundled(golang(golang.org/x/sync)) = 0.10.0 Provides: bundled(golang(golang.org/x/sys)) = 0.28.0 Provides: bundled(golang(golang.org/x/telemetry)) = 0.0.0.20241204182053.c0ac0e154df3 From 5d3dfa13bf1c73286db9fc3da96e0e1f53327e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Thu, 8 May 2025 10:59:29 +0200 Subject: [PATCH 55/75] Add wasm and fips140 libs to the installation Resolves: rhbz#2356269 --- golang.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/golang.spec b/golang.spec index f01d3a4..19f95ec 100644 --- a/golang.spec +++ b/golang.spec @@ -502,6 +502,8 @@ fi %dir %{goroot} %{goroot}/api/ %{goroot}/lib/time/ +%{goroot}/lib/wasm/ +%{goroot}/lib/fips140/ # ensure directory ownership, so they are cleaned up if empty %dir %{gopath} From 771162273711c0da18c40ae2f476cf6c72137da6 Mon Sep 17 00:00:00 2001 From: Packit Date: Thu, 5 Jun 2025 20:53:19 +0000 Subject: [PATCH 56/75] Update to 1.24.4 upstream release - Resolves: rhbz#2370501 Upstream tag: go1.24.4 Upstream commit: 6796ebb2 Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + README.packit | 2 +- golang.spec | 2 +- sources | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index c2b1923..f178c4c 100644 --- a/.gitignore +++ b/.gitignore @@ -164,3 +164,4 @@ /go1.24.1.src.tar.gz /go1.24.2.src.tar.gz /go1.24.3.src.tar.gz +/go1.24.4.src.tar.gz diff --git a/README.packit b/README.packit index 807ffc6..6beb40f 100644 --- a/README.packit +++ b/README.packit @@ -1,3 +1,3 @@ This repository is maintained by packit. https://packit.dev/ -The file was generated using packit 1.6.0.post1.dev2+gd5a7662a. +The file was generated using packit 1.8.0.post1.dev31+g9980e597. diff --git a/golang.spec b/golang.spec index 19f95ec..9a4c3d3 100644 --- a/golang.spec +++ b/golang.spec @@ -101,7 +101,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.24 #global go_prerelease rc3 -%global go_patch 3 +%global go_patch 4 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index 0e29767..69f0990 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.24.3.src.tar.gz) = 05d19372fb923eeea19395b4de569d2ecfec7fadf2d8236d47cd667982de51c569e9816372cb79e32166553f9bcbe68f7bc2a6ded5655809b1caf5bd941011e7 +SHA512 (go1.24.4.src.tar.gz) = b785583fc53d62094b2de793a0e3281a26d2de17897a35b378fc2d13cb912ca473c37a7bae54a50660141809d5d0a70a97663d406cf30d7f0221ecbb5ffddec6 From 7d06f9cac2eadce6e77af58b5430f1a4a8270d0f Mon Sep 17 00:00:00 2001 From: Packit Date: Tue, 8 Jul 2025 18:00:29 +0000 Subject: [PATCH 57/75] Update to 1.24.5 upstream release - Resolves: rhbz#2378705 Upstream tag: go1.24.5 Upstream commit: 9d828e80 Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + README.packit | 2 +- golang.spec | 2 +- sources | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index f178c4c..253b962 100644 --- a/.gitignore +++ b/.gitignore @@ -165,3 +165,4 @@ /go1.24.2.src.tar.gz /go1.24.3.src.tar.gz /go1.24.4.src.tar.gz +/go1.24.5.src.tar.gz diff --git a/README.packit b/README.packit index 6beb40f..dde2a46 100644 --- a/README.packit +++ b/README.packit @@ -1,3 +1,3 @@ This repository is maintained by packit. https://packit.dev/ -The file was generated using packit 1.8.0.post1.dev31+g9980e597. +The file was generated using packit 1.9.0.post1.dev4+g48b4c222. diff --git a/golang.spec b/golang.spec index 9a4c3d3..baf6991 100644 --- a/golang.spec +++ b/golang.spec @@ -101,7 +101,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.24 #global go_prerelease rc3 -%global go_patch 4 +%global go_patch 5 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index 69f0990..eed8ece 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.24.4.src.tar.gz) = b785583fc53d62094b2de793a0e3281a26d2de17897a35b378fc2d13cb912ca473c37a7bae54a50660141809d5d0a70a97663d406cf30d7f0221ecbb5ffddec6 +SHA512 (go1.24.5.src.tar.gz) = 917cd6ac83e3370227da40f8490697e8638847e9279ed1806044a173d3b52829c67c429990db92d8aadcfba6a37bfc00114c1ecec3ac387a781bb7edc8dcab22 From 8afc7c42283fefa6ed8cd9fcbb7b46dde0fb2178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Sat, 19 Jul 2025 20:41:32 +0200 Subject: [PATCH 58/75] Update to Go 1.25rc2 Update .packit.yaml for Fedora 41 Add skip_lsan_tests.patch Remove 0001-Modify-go.env.patch --- .gitignore | 2 ++ .packit.yaml | 14 ++++---------- 0001-Modify-go.env.patch | 30 ------------------------------ golang.spec | 38 ++++++++++++++++++++------------------ skip_lsan_tests.patch | 25 +++++++++++++++++++++++++ sources | 2 +- 6 files changed, 52 insertions(+), 59 deletions(-) delete mode 100644 0001-Modify-go.env.patch create mode 100644 skip_lsan_tests.patch diff --git a/.gitignore b/.gitignore index 253b962..5e9a917 100644 --- a/.gitignore +++ b/.gitignore @@ -166,3 +166,5 @@ /go1.24.3.src.tar.gz /go1.24.4.src.tar.gz /go1.24.5.src.tar.gz +/go1.25rc1.src.tar.gz +/go1.25rc2.src.tar.gz diff --git a/.packit.yaml b/.packit.yaml index f12f73e..f05ef2c 100644 --- a/.packit.yaml +++ b/.packit.yaml @@ -12,18 +12,12 @@ actions: - bash -c "echo - New release ${PACKIT_PROJECT_VERSION}" jobs: - # Fedora 40 follows Go 1.23 - # https://pagure.io/fesco/issue/3372 - - job: pull_from_upstream - trigger: release - dist_git_branches: fedora-40 - upstream_tag_include: "^go1.23.+" - - # Fedora 41 follows Go 1.23 + # Fedora 41 follows Go 1.24 + # https://pagure.io/fesco/issue/3435 - job: pull_from_upstream trigger: release dist_git_branches: fedora-41 - upstream_tag_include: "^go1.23.+" + upstream_tag_include: "^go1.24.+" # Fedora 42 follows Go 1.24 - job: pull_from_upstream @@ -35,7 +29,7 @@ jobs: - job: pull_from_upstream trigger: release dist_git_branches: fedora-rawhide - upstream_tag_include: "^go1.24.+" + upstream_tag_include: "^go1.25.+" # Run Koji builds when Packit pull requests are merged - job: koji_build diff --git a/0001-Modify-go.env.patch b/0001-Modify-go.env.patch deleted file mode 100644 index d0b18c7..0000000 --- a/0001-Modify-go.env.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 52d9cfec8124a9c7382bed5284246d9b18a21eb4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= -Date: Wed, 16 Aug 2023 07:06:38 +0200 -Subject: [PATCH] Modify go.env - -Change GOPROXY, GOSUMDB, and GOTOOLCHAIN ---- - go.env | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/go.env b/go.env -index 6ff2b921d4..087208cd7c 100644 ---- a/go.env -+++ b/go.env -@@ -4,9 +4,9 @@ - - # Use the Go module mirror and checksum database by default. - # See https://proxy.golang.org for details. --GOPROXY=https://proxy.golang.org,direct --GOSUMDB=sum.golang.org -+GOPROXY=direct -+GOSUMDB=off - - # Automatically download newer toolchains as directed by go.mod files. - # See https://go.dev/doc/toolchain for details. --GOTOOLCHAIN=auto -+GOTOOLCHAIN=local --- -2.41.0 - diff --git a/golang.spec b/golang.spec index baf6991..3368d30 100644 --- a/golang.spec +++ b/golang.spec @@ -99,13 +99,13 @@ %endif # Comment out go_prerelease and go_patch as needed -%global go_api 1.24 -#global go_prerelease rc3 -%global go_patch 5 +%global go_api 1.25 +%global go_prerelease rc2 +#global go_patch 4 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} - + Name: golang Version: %{go_version} Release: %autorelease @@ -135,30 +135,32 @@ BuildRequires: pcre2-devel, glibc-static, perl-interpreter, procps-ng Provides: go = %{version}-%{release} # Bundled/Vendored provides generated by bundled-deps.sh based on the in tree module data -Provides: bundled(golang(github.com/google/pprof)) = 0.0.0.20241101162523.b92577c0c142 +Provides: bundled(golang(github.com/google/pprof)) = 0.0.0.20250208200701.d0013a598941 Provides: bundled(golang(github.com/ianlancetaylor/demangle)) = 0.0.0.20240912202439.0a2b6291aafd -Provides: bundled(golang(golang.org/x/arch)) = 0.12.0 -Provides: bundled(golang(golang.org/x/build)) = 0.0.0.20241205234318.b850320af2a4 -Provides: bundled(golang(golang.org/x/crypto)) = 0.30.0 -Provides: bundled(golang(golang.org/x/mod)) = 0.22.0 -Provides: bundled(golang(golang.org/x/net)) = 0.32.1.0.20250304185419.76f9bf3279ef -Provides: bundled(golang(golang.org/x/sync)) = 0.10.0 -Provides: bundled(golang(golang.org/x/sys)) = 0.28.0 -Provides: bundled(golang(golang.org/x/telemetry)) = 0.0.0.20241204182053.c0ac0e154df3 -Provides: bundled(golang(golang.org/x/term)) = 0.27.0 -Provides: bundled(golang(golang.org/x/text)) = 0.21.0 -Provides: bundled(golang(golang.org/x/tools)) = 0.28.1.0.20250131145412.98746475647e +Provides: bundled(golang(golang.org/x/arch)) = 0.18.1.0.20250605182141.b2f4e2807dec +Provides: bundled(golang(golang.org/x/build)) = 0.0.0.20250606033421.8c8ff6f34a83 +Provides: bundled(golang(golang.org/x/crypto)) = 0.39.0 +Provides: bundled(golang(golang.org/x/mod)) = 0.25.0 +Provides: bundled(golang(golang.org/x/net)) = 0.41.0 +Provides: bundled(golang(golang.org/x/sync)) = 0.15.0 +Provides: bundled(golang(golang.org/x/sys)) = 0.33.0 +Provides: bundled(golang(golang.org/x/telemetry)) = 0.0.0.20250606142133.60998feb31a8 +Provides: bundled(golang(golang.org/x/term)) = 0.32.0 +Provides: bundled(golang(golang.org/x/text)) = 0.26.0 +Provides: bundled(golang(golang.org/x/tools)) = 0.27.0 +Provides: bundled(golang(golang.org/x/tools)) = 0.34.0 Provides: bundled(golang(rsc.io/markdown)) = 0.0.0.20240306144322.0bf8f97ee8ef Requires: %{name}-bin = %{version}-%{release} Requires: %{name}-src = %{version}-%{release} Requires: go-filesystem -Patch1: 0001-Modify-go.env.patch Patch5: 0005-Skip-TestCrashDumpsAllThreads.patch Patch6: 0006-Default-to-ld.bfd-on-ARM64.patch # Related to https://gcc.gnu.org/PR118497 Patch8: fix_cgo_panic-with-gcc15-in-368.patch +# Related to https://github.com/golang/go/issues/74476 +Patch9: skip_lsan_tests.patch # Having documentation separate was broken Obsoletes: %{name}-docs < 1.1-4 @@ -397,7 +399,7 @@ echo "== 4 ==" echo "%%{goroot}/$file" >> $shared_list echo "%%{golibdir}/$(basename $file)" >> $shared_list done - + find pkg/*_dynlink/ -type d -printf '%%%dir %{goroot}/%p\n' >> $shared_list find pkg/*_dynlink/ ! -type d -printf '%{goroot}/%p\n' >> $shared_list %endif diff --git a/skip_lsan_tests.patch b/skip_lsan_tests.patch new file mode 100644 index 0000000..b98e486 --- /dev/null +++ b/skip_lsan_tests.patch @@ -0,0 +1,25 @@ +From 958f06663d81dd4b946fce963b9f985f68da6212 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= +Date: Wed, 16 Jul 2025 13:14:03 +0200 +Subject: [PATCH] Skip lsan_test.go in aarch64 + +Reference: https://github.com/golang/go/issues/74476 +--- + src/cmd/cgo/internal/testsanitizers/lsan_test.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cmd/cgo/internal/testsanitizers/lsan_test.go b/src/cmd/cgo/internal/testsanitizers/lsan_test.go +index 4dde3d20ec..3bcf0eba51 100644 +--- a/src/cmd/cgo/internal/testsanitizers/lsan_test.go ++++ b/src/cmd/cgo/internal/testsanitizers/lsan_test.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build linux || (freebsd && amd64) ++//go:build (linux && !arm64) || (freebsd && amd64) + + package sanitizers_test + +-- +2.50.1 diff --git a/sources b/sources index eed8ece..0cf2dad 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.24.5.src.tar.gz) = 917cd6ac83e3370227da40f8490697e8638847e9279ed1806044a173d3b52829c67c429990db92d8aadcfba6a37bfc00114c1ecec3ac387a781bb7edc8dcab22 +SHA512 (go1.25rc2.src.tar.gz) = a63410d2ac9690146ae036a0d911939f6ab4ebb160f39022bd4350090572668f848f5f430a817c5bc70534d7b52470de21d7f3b9b208a8fd9e3dc570fc9d0e80 From dc534e467ca520a64f8af2b341f20adda7d4c582 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Wed, 23 Jul 2025 22:55:49 +0000 Subject: [PATCH 59/75] Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild From 1a696ebca1b2d5227921924d3f9885e18cf445b5 Mon Sep 17 00:00:00 2001 From: Maxwell G Date: Thu, 24 Jul 2025 12:25:32 -0500 Subject: [PATCH 60/75] Partially restore the downstream go.env patch - Keep the GOPROXY and GOSUMDB defaults but add additional explanatory comments. - Restore GOTOOLCHAIN=local - Set GOEXPERIMENT=nodwarf5 --- 0001-Modify-go.env.patch | 42 ++++++++++++++++++++++++++++++++++++++++ golang.spec | 1 + 2 files changed, 43 insertions(+) create mode 100644 0001-Modify-go.env.patch diff --git a/0001-Modify-go.env.patch b/0001-Modify-go.env.patch new file mode 100644 index 0000000..6a458b2 --- /dev/null +++ b/0001-Modify-go.env.patch @@ -0,0 +1,42 @@ +From 39432f71436c41201450a523dc41035c92d27569 Mon Sep 17 00:00:00 2001 +From: Maxwell G +Date: Thu, 24 Jul 2025 12:23:59 -0500 +Subject: [PATCH] Modify go.env + +--- + go.env | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/go.env b/go.env +index 6ff2b92..5508440 100644 +--- a/go.env ++++ b/go.env +@@ -4,9 +4,24 @@ + + # Use the Go module mirror and checksum database by default. + # See https://proxy.golang.org for details. ++# ++# NOTE(downstream): We used to disable the Google Go proxy with GOPROXY=direct and ++# disable the GOSUMDB for historical and priavcy reasons, but it caused severe ++# performance degradations, so we reverted to the default upstream configuration. ++# as of https://fedoraproject.org/wiki/Changes/golang1.25. ++# To preserve the previous behavior, set "GOPROXY=direct" and "GOSUMDB=off". + GOPROXY=https://proxy.golang.org,direct + GOSUMDB=sum.golang.org + + # Automatically download newer toolchains as directed by go.mod files. + # See https://go.dev/doc/toolchain for details. +-GOTOOLCHAIN=auto ++# ++# NOTE(downstream): We change this default from auto to local so that the ++# distribution-packaged Go toolchain is always used and go doesn't ++# automatically download pre-compiled alternative versions. ++GOTOOLCHAIN=local ++ ++# NOTE(downstream): https://sourceware.org/bugzilla/show_bug.cgi?id=33204 ++# The dwarf5 data emitted by default in Go 1.25+ is incompatible with debugedit ++# and breaks debugdata collection. ++GOEXPERIMENT=nodwarf5 +-- +2.50.1 + diff --git a/golang.spec b/golang.spec index 3368d30..73e7c2d 100644 --- a/golang.spec +++ b/golang.spec @@ -155,6 +155,7 @@ Requires: %{name}-bin = %{version}-%{release} Requires: %{name}-src = %{version}-%{release} Requires: go-filesystem +Patch1: 0001-Modify-go.env.patch Patch5: 0005-Skip-TestCrashDumpsAllThreads.patch Patch6: 0006-Default-to-ld.bfd-on-ARM64.patch # Related to https://gcc.gnu.org/PR118497 From ecc9df192feda3e07fc0cf3306b479ce8d5341f0 Mon Sep 17 00:00:00 2001 From: Packit Date: Tue, 12 Aug 2025 21:38:21 +0000 Subject: [PATCH 61/75] Update to 1.25.0 upstream release - Resolves: rhbz#2388116 Upstream tag: go1.25.0 Upstream commit: 6e676ab2 Commit authored by Packit automation (https://packit.dev/) --- README.packit | 2 +- golang.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.packit b/README.packit index dde2a46..3ad54d6 100644 --- a/README.packit +++ b/README.packit @@ -1,3 +1,3 @@ This repository is maintained by packit. https://packit.dev/ -The file was generated using packit 1.9.0.post1.dev4+g48b4c222. +The file was generated using packit 1.11.0. diff --git a/golang.spec b/golang.spec index 73e7c2d..9f4b5af 100644 --- a/golang.spec +++ b/golang.spec @@ -103,7 +103,7 @@ %global go_prerelease rc2 #global go_patch 4 -%global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} +%global go_version 1.25.0 %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} Name: golang From d0bdcaaac7b19319f13d50ee80c38a3b1caa2754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Wed, 13 Aug 2025 08:06:53 +0200 Subject: [PATCH 62/75] Update to Go 1.25.0 revert go_version change made by Packit --- .gitignore | 1 + golang.spec | 6 +++--- sources | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 5e9a917..b3e1964 100644 --- a/.gitignore +++ b/.gitignore @@ -168,3 +168,4 @@ /go1.24.5.src.tar.gz /go1.25rc1.src.tar.gz /go1.25rc2.src.tar.gz +/go1.25.0.src.tar.gz diff --git a/golang.spec b/golang.spec index 9f4b5af..e71c057 100644 --- a/golang.spec +++ b/golang.spec @@ -100,10 +100,10 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.25 -%global go_prerelease rc2 -#global go_patch 4 +#global go_prerelease rc2 +%global go_patch 0 -%global go_version 1.25.0 +%global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} Name: golang diff --git a/sources b/sources index 0cf2dad..71687e4 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.25rc2.src.tar.gz) = a63410d2ac9690146ae036a0d911939f6ab4ebb160f39022bd4350090572668f848f5f430a817c5bc70534d7b52470de21d7f3b9b208a8fd9e3dc570fc9d0e80 +SHA512 (go1.25.0.src.tar.gz) = 45030cd02ab0ed4feb74e12ad9dde544bf2255c4d1a48655fca5b643bbe690c75ea3dfac74a0e3e3c707c5af5e9171ae383a7a322e70fe824f9a47b6ffd42201 From 56d6b65b5bb81baebd8be5e587c03fcfb77783b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Wed, 13 Aug 2025 08:24:19 +0200 Subject: [PATCH 63/75] Add Fedora 43 --- .packit.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.packit.yaml b/.packit.yaml index f05ef2c..78727ca 100644 --- a/.packit.yaml +++ b/.packit.yaml @@ -25,6 +25,12 @@ jobs: dist_git_branches: fedora-42 upstream_tag_include: "^go1.24.+" + # Fedora 43 follows Go 1.25 + - job: pull_from_upstream + trigger: release + dist_git_branches: fedora-43 + upstream_tag_include: "^go1.25.+" + # Fedora Rawhide follows the latest version - job: pull_from_upstream trigger: release From c1d0accc88066aab3f95392a62bc50f18b0e10bb Mon Sep 17 00:00:00 2001 From: Packit Date: Wed, 3 Sep 2025 19:40:28 +0000 Subject: [PATCH 64/75] Update to 1.25.1 upstream release - Resolves: rhbz#2392955 Upstream tag: go1.25.1 Upstream commit: 56ebf80e Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + README.packit | 2 +- golang.spec | 2 +- sources | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index b3e1964..1aac595 100644 --- a/.gitignore +++ b/.gitignore @@ -169,3 +169,4 @@ /go1.25rc1.src.tar.gz /go1.25rc2.src.tar.gz /go1.25.0.src.tar.gz +/go1.25.1.src.tar.gz diff --git a/README.packit b/README.packit index 3ad54d6..fb341a1 100644 --- a/README.packit +++ b/README.packit @@ -1,3 +1,3 @@ This repository is maintained by packit. https://packit.dev/ -The file was generated using packit 1.11.0. +The file was generated using packit 1.11.0.post1.dev7+gfdcdf3a32. diff --git a/golang.spec b/golang.spec index e71c057..fffd62b 100644 --- a/golang.spec +++ b/golang.spec @@ -101,7 +101,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.25 #global go_prerelease rc2 -%global go_patch 0 +%global go_patch 1 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index 71687e4..3706469 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.25.0.src.tar.gz) = 45030cd02ab0ed4feb74e12ad9dde544bf2255c4d1a48655fca5b643bbe690c75ea3dfac74a0e3e3c707c5af5e9171ae383a7a322e70fe824f9a47b6ffd42201 +SHA512 (go1.25.1.src.tar.gz) = e77ae799a0dcd4ded40a196c3645da5b7e808e417831d2c5441387b0fd0ed5f946b678305294c52fda0a258889225c24c6073bb0973c3531ba4aa107b6afe849 From e2a58b1cf3e1d9f216bfcd7b32e60cef67387228 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Tue, 29 Jul 2025 21:49:51 +0200 Subject: [PATCH 65/75] Remove unused patch --- ff2636f.patch | 234 -------------------------------------------------- 1 file changed, 234 deletions(-) delete mode 100644 ff2636f.patch diff --git a/ff2636f.patch b/ff2636f.patch deleted file mode 100644 index 5baed13..0000000 --- a/ff2636f.patch +++ /dev/null @@ -1,234 +0,0 @@ -From ff2636f45e0087a1c6d8e895257d9c4729710811 Mon Sep 17 00:00:00 2001 -From: Michael Pratt -Date: Thu, 03 Apr 2025 03:26:25 +0000 -Subject: [PATCH] [release-branch.go1.24] runtime: cleanup M vgetrandom state before dropping P - -When an M is destroyed, we put its vgetrandom state back on the shared -list for another M to reuse. This list is simply a slice, so appending -to the slice may allocate. Currently this operation is performed in -mdestroy, after the P is released, meaning allocation is not allowed. - -More the cleanup earlier in mdestroy when allocation is still OK. - -Also add //go:nowritebarrierrec to mdestroy since it runs without a P, -which would have caught this bug. - -Fixes #73144. -For #73141. - -Change-Id: I6a6a636c3fbf5c6eec09d07a260e39dbb4d2db12 -Reviewed-on: https://go-review.googlesource.com/c/go/+/662455 -Reviewed-by: Jason Donenfeld -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Keith Randall -Reviewed-by: Keith Randall -(cherry picked from commit 0b31e6d4cc804ab76ae8ced151ee2f50657aec14) ---- - -diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go -index cf163a6..ded821b 100644 ---- a/src/runtime/os3_solaris.go -+++ b/src/runtime/os3_solaris.go -@@ -234,8 +234,11 @@ - getg().m.procid = 0 - } - --// Called from exitm, but not from drop, to undo the effect of thread-owned -+// Called from mexit, but not from dropm, to undo the effect of thread-owned - // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. -+// -+// This always runs without a P, so //go:nowritebarrierrec is required. -+//go:nowritebarrierrec - func mdestroy(mp *m) { - } - -diff --git a/src/runtime/os_aix.go b/src/runtime/os_aix.go -index 93464cb..1b483c2 100644 ---- a/src/runtime/os_aix.go -+++ b/src/runtime/os_aix.go -@@ -186,8 +186,11 @@ - getg().m.procid = 0 - } - --// Called from exitm, but not from drop, to undo the effect of thread-owned -+// Called from mexit, but not from dropm, to undo the effect of thread-owned - // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. -+// -+// This always runs without a P, so //go:nowritebarrierrec is required. -+//go:nowritebarrierrec - func mdestroy(mp *m) { - } - -diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go -index 0ecbea7..6eab3b5 100644 ---- a/src/runtime/os_darwin.go -+++ b/src/runtime/os_darwin.go -@@ -344,8 +344,11 @@ - getg().m.procid = 0 - } - --// Called from exitm, but not from drop, to undo the effect of thread-owned -+// Called from mexit, but not from dropm, to undo the effect of thread-owned - // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. -+// -+// This always runs without a P, so //go:nowritebarrierrec is required. -+//go:nowritebarrierrec - func mdestroy(mp *m) { - } - -diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go -index a02696e..9b32350 100644 ---- a/src/runtime/os_dragonfly.go -+++ b/src/runtime/os_dragonfly.go -@@ -216,8 +216,11 @@ - getg().m.procid = 0 - } - --// Called from exitm, but not from drop, to undo the effect of thread-owned -+// Called from mexit, but not from dropm, to undo the effect of thread-owned - // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. -+// -+// This always runs without a P, so //go:nowritebarrierrec is required. -+//go:nowritebarrierrec - func mdestroy(mp *m) { - } - -diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go -index 8b3c4d0..fb46b81 100644 ---- a/src/runtime/os_linux.go -+++ b/src/runtime/os_linux.go -@@ -412,13 +412,12 @@ - getg().m.procid = 0 - } - --// Called from exitm, but not from drop, to undo the effect of thread-owned -+// Called from mexit, but not from dropm, to undo the effect of thread-owned - // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. -+// -+// This always runs without a P, so //go:nowritebarrierrec is required. -+//go:nowritebarrierrec - func mdestroy(mp *m) { -- if mp.vgetrandomState != 0 { -- vgetrandomPutState(mp.vgetrandomState) -- mp.vgetrandomState = 0 -- } - } - - // #ifdef GOARCH_386 -diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go -index 735ace2..a06e5fe 100644 ---- a/src/runtime/os_netbsd.go -+++ b/src/runtime/os_netbsd.go -@@ -320,8 +320,11 @@ - // must continue working after unminit. - } - --// Called from exitm, but not from drop, to undo the effect of thread-owned -+// Called from mexit, but not from dropm, to undo the effect of thread-owned - // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. -+// -+// This always runs without a P, so //go:nowritebarrierrec is required. -+//go:nowritebarrierrec - func mdestroy(mp *m) { - } - -diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go -index 574bfa8..4ce4c3c 100644 ---- a/src/runtime/os_openbsd.go -+++ b/src/runtime/os_openbsd.go -@@ -182,8 +182,11 @@ - getg().m.procid = 0 - } - --// Called from exitm, but not from drop, to undo the effect of thread-owned -+// Called from mexit, but not from dropm, to undo the effect of thread-owned - // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. -+// -+// This always runs without a P, so //go:nowritebarrierrec is required. -+//go:nowritebarrierrec - func mdestroy(mp *m) { - } - -diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go -index 2dbb42a..3b5965a 100644 ---- a/src/runtime/os_plan9.go -+++ b/src/runtime/os_plan9.go -@@ -217,8 +217,11 @@ - func unminit() { - } - --// Called from exitm, but not from drop, to undo the effect of thread-owned -+// Called from mexit, but not from dropm, to undo the effect of thread-owned - // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. -+// -+// This always runs without a P, so //go:nowritebarrierrec is required. -+//go:nowritebarrierrec - func mdestroy(mp *m) { - } - -diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go -index 7183e79..54407a3 100644 ---- a/src/runtime/os_windows.go -+++ b/src/runtime/os_windows.go -@@ -906,9 +906,11 @@ - mp.procid = 0 - } - --// Called from exitm, but not from drop, to undo the effect of thread-owned -+// Called from mexit, but not from dropm, to undo the effect of thread-owned - // resources in minit, semacreate, or elsewhere. Do not take locks after calling this. - // -+// This always runs without a P, so //go:nowritebarrierrec is required. -+//go:nowritebarrierrec - //go:nosplit - func mdestroy(mp *m) { - if mp.highResTimer != 0 { -diff --git a/src/runtime/proc.go b/src/runtime/proc.go -index e9873e5..21bee4d 100644 ---- a/src/runtime/proc.go -+++ b/src/runtime/proc.go -@@ -1935,6 +1935,9 @@ - mp.gsignal = nil - } - -+ // Free vgetrandom state. -+ vgetrandomDestroy(mp) -+ - // Remove m from allm. - lock(&sched.lock) - for pprev := &allm; *pprev != nil; pprev = &(*pprev).alllink { -diff --git a/src/runtime/vgetrandom_linux.go b/src/runtime/vgetrandom_linux.go -index a6ec4b7..40be022 100644 ---- a/src/runtime/vgetrandom_linux.go -+++ b/src/runtime/vgetrandom_linux.go -@@ -73,9 +73,16 @@ - return state - } - --func vgetrandomPutState(state uintptr) { -+// Free vgetrandom state from the M (if any) prior to destroying the M. -+// -+// This may allocate, so it must have a P. -+func vgetrandomDestroy(mp *m) { -+ if mp.vgetrandomState == 0 { -+ return -+ } -+ - lock(&vgetrandomAlloc.statesLock) -- vgetrandomAlloc.states = append(vgetrandomAlloc.states, state) -+ vgetrandomAlloc.states = append(vgetrandomAlloc.states, mp.vgetrandomState) - unlock(&vgetrandomAlloc.statesLock) - } - -diff --git a/src/runtime/vgetrandom_unsupported.go b/src/runtime/vgetrandom_unsupported.go -index 070392c..43c53e1 100644 ---- a/src/runtime/vgetrandom_unsupported.go -+++ b/src/runtime/vgetrandom_unsupported.go -@@ -13,6 +13,6 @@ - return -1, false - } - --func vgetrandomPutState(state uintptr) {} -+func vgetrandomDestroy(mp *m) {} - - func vgetrandomInit() {} From 4479594a302682d636aac177cdbd1b3d0c99dd77 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Tue, 29 Jul 2025 21:50:40 +0200 Subject: [PATCH 66/75] Drop old check on RHEL6 and Fedora --- golang.spec | 4 ---- 1 file changed, 4 deletions(-) diff --git a/golang.spec b/golang.spec index fffd62b..ae9cc2c 100644 --- a/golang.spec +++ b/golang.spec @@ -123,11 +123,7 @@ BuildRequires: gcc-go >= 5 %else BuildRequires: golang > 1.4 %endif -%if 0%{?rhel} > 6 || 0%{?fedora} > 0 BuildRequires: hostname -%else -BuildRequires: net-tools -%endif # for tests BuildRequires: pcre2-devel, glibc-static, perl-interpreter, procps-ng From 5180b4660210892cbb5aa8836719e010935d3569 Mon Sep 17 00:00:00 2001 From: Mikel Olasagasti Uranga Date: Tue, 29 Jul 2025 21:54:59 +0200 Subject: [PATCH 67/75] Drop check for old Releases and recommend git-core `git-core` package provides `git` command and doesn't require the extra modules `git` package provides to work with remote modules, avoiding having to install multiple depenencies. --- golang.spec | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/golang.spec b/golang.spec index ae9cc2c..1a08cd1 100644 --- a/golang.spec +++ b/golang.spec @@ -252,11 +252,8 @@ Requires(preun): %{_sbindir}/update-alternatives # This is an odd issue, still looking for a better fix. Requires: glibc Requires: gcc -%if 0%{?rhel} && 0%{?rhel} < 8 -Requires: git, subversion, mercurial -%else -Recommends: git, subversion, mercurial -%endif +Recommends: git-core, subversion, mercurial + %description bin %{summary} From 5d71cf066b2236eefb9f7e0b93ea7ef0973a3f9e Mon Sep 17 00:00:00 2001 From: Packit Date: Tue, 7 Oct 2025 20:06:02 +0000 Subject: [PATCH 68/75] Update to 1.25.2 upstream release - Resolves: rhbz#2402368 Upstream tag: go1.25.2 Upstream commit: bed6c81c Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + golang.spec | 2 +- sources | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 1aac595..40dc707 100644 --- a/.gitignore +++ b/.gitignore @@ -170,3 +170,4 @@ /go1.25rc2.src.tar.gz /go1.25.0.src.tar.gz /go1.25.1.src.tar.gz +/go1.25.2.src.tar.gz diff --git a/golang.spec b/golang.spec index 1a08cd1..72fd53a 100644 --- a/golang.spec +++ b/golang.spec @@ -101,7 +101,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.25 #global go_prerelease rc2 -%global go_patch 1 +%global go_patch 2 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index 3706469..216a5f1 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.25.1.src.tar.gz) = e77ae799a0dcd4ded40a196c3645da5b7e808e417831d2c5441387b0fd0ed5f946b678305294c52fda0a258889225c24c6073bb0973c3531ba4aa107b6afe849 +SHA512 (go1.25.2.src.tar.gz) = 2700ceca314bb78b8ff97aa8703442b60eceb3acbad46b7959739bb0399174f27af372c7f72cd1adb83997adacbf43e2e2572e85fa5cf2a18271d0ef1ee0b8b4 From 4a9bd423ee10bbea7a4025b4d29b7c6c4b03dca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Fri, 10 Oct 2025 17:09:35 +0200 Subject: [PATCH 69/75] rebuild From ff6333f2c18f880013681f415d2a712488b1e8a8 Mon Sep 17 00:00:00 2001 From: Packit Date: Tue, 14 Oct 2025 00:15:00 +0000 Subject: [PATCH 70/75] Update to 1.25.3 upstream release - Resolves: rhbz#2403668 Upstream tag: go1.25.3 Upstream commit: 28622c19 Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + golang.spec | 2 +- sources | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 40dc707..edb848f 100644 --- a/.gitignore +++ b/.gitignore @@ -171,3 +171,4 @@ /go1.25.0.src.tar.gz /go1.25.1.src.tar.gz /go1.25.2.src.tar.gz +/go1.25.3.src.tar.gz diff --git a/golang.spec b/golang.spec index 72fd53a..b1eebb0 100644 --- a/golang.spec +++ b/golang.spec @@ -101,7 +101,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.25 #global go_prerelease rc2 -%global go_patch 2 +%global go_patch 3 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index 216a5f1..e5e469a 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.25.2.src.tar.gz) = 2700ceca314bb78b8ff97aa8703442b60eceb3acbad46b7959739bb0399174f27af372c7f72cd1adb83997adacbf43e2e2572e85fa5cf2a18271d0ef1ee0b8b4 +SHA512 (go1.25.3.src.tar.gz) = 91d32bbff864c06b5ee7b914d3d95c59462352a4c395adba85eaab72704a8aa4d19ac2a361ed64774dce3c8e01a8d4feadf1a788814f6d7b4072a3bdfefbb3b4 From abe2807b6dc3e3714b6d3edac9a8100463bae495 Mon Sep 17 00:00:00 2001 From: Packit Date: Wed, 5 Nov 2025 21:35:52 +0000 Subject: [PATCH 71/75] Update to 1.25.4 upstream release - Resolves: rhbz#2412967 Upstream tag: go1.25.4 Upstream commit: f2cd93aa Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + README.packit | 2 +- golang.spec | 2 +- sources | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index edb848f..7931fc1 100644 --- a/.gitignore +++ b/.gitignore @@ -172,3 +172,4 @@ /go1.25.1.src.tar.gz /go1.25.2.src.tar.gz /go1.25.3.src.tar.gz +/go1.25.4.src.tar.gz diff --git a/README.packit b/README.packit index fb341a1..2511bf4 100644 --- a/README.packit +++ b/README.packit @@ -1,3 +1,3 @@ This repository is maintained by packit. https://packit.dev/ -The file was generated using packit 1.11.0.post1.dev7+gfdcdf3a32. +The file was generated using packit 1.12.0. diff --git a/golang.spec b/golang.spec index b1eebb0..0c1c238 100644 --- a/golang.spec +++ b/golang.spec @@ -101,7 +101,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.25 #global go_prerelease rc2 -%global go_patch 3 +%global go_patch 4 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index e5e469a..3227932 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.25.3.src.tar.gz) = 91d32bbff864c06b5ee7b914d3d95c59462352a4c395adba85eaab72704a8aa4d19ac2a361ed64774dce3c8e01a8d4feadf1a788814f6d7b4072a3bdfefbb3b4 +SHA512 (go1.25.4.src.tar.gz) = 6892c2cadc22bce82250f52c754053a70e9e594ec53754a1bed6b9594e8faffda1a6b052d6e298692948740ac0079697294430a4138a842ea298877449cf01cd From 7f14ad762bdd8b9d7b9a11a6bcfb0d726fac42a5 Mon Sep 17 00:00:00 2001 From: David Abdurachmanov Date: Fri, 24 Oct 2025 10:47:26 +0300 Subject: [PATCH 72/75] Skip lsan tests on riscv64 These tests are failing the same way on riscv64 too. Signed-off-by: David Abdurachmanov --- skip_lsan_tests.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skip_lsan_tests.patch b/skip_lsan_tests.patch index b98e486..9a47ee7 100644 --- a/skip_lsan_tests.patch +++ b/skip_lsan_tests.patch @@ -17,7 +17,7 @@ index 4dde3d20ec..3bcf0eba51 100644 // license that can be found in the LICENSE file. -//go:build linux || (freebsd && amd64) -+//go:build (linux && !arm64) || (freebsd && amd64) ++//go:build (linux && !(arm64 || riscv64)) || (freebsd && amd64) package sanitizers_test From d9efef266e8b2c31461cc4e0ccc7045f3defff41 Mon Sep 17 00:00:00 2001 From: Packit Date: Fri, 5 Dec 2025 11:49:33 +0000 Subject: [PATCH 73/75] Update to 1.25.5 upstream release - Resolves: rhbz#2419205 Upstream tag: go1.25.5 Upstream commit: fefb02ad Commit authored by Packit automation (https://packit.dev/) --- .gitignore | 1 + README.packit | 2 +- golang.spec | 2 +- sources | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 7931fc1..0c454c2 100644 --- a/.gitignore +++ b/.gitignore @@ -173,3 +173,4 @@ /go1.25.2.src.tar.gz /go1.25.3.src.tar.gz /go1.25.4.src.tar.gz +/go1.25.5.src.tar.gz diff --git a/README.packit b/README.packit index 2511bf4..b4b46e3 100644 --- a/README.packit +++ b/README.packit @@ -1,3 +1,3 @@ This repository is maintained by packit. https://packit.dev/ -The file was generated using packit 1.12.0. +The file was generated using packit 1.12.0.post1.dev20+g7d30dac21. diff --git a/golang.spec b/golang.spec index 0c1c238..61586c5 100644 --- a/golang.spec +++ b/golang.spec @@ -101,7 +101,7 @@ # Comment out go_prerelease and go_patch as needed %global go_api 1.25 #global go_prerelease rc2 -%global go_patch 4 +%global go_patch 5 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} diff --git a/sources b/sources index 3227932..6e447e8 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.25.4.src.tar.gz) = 6892c2cadc22bce82250f52c754053a70e9e594ec53754a1bed6b9594e8faffda1a6b052d6e298692948740ac0079697294430a4138a842ea298877449cf01cd +SHA512 (go1.25.5.src.tar.gz) = 97ec368521253bce610e1e3a6f10460f4a38eba440289553a40ab27afcdf2bb9b426d150ffaa3be8db50e84a00a4eb723a631ebc4f39168bc133bf7b2f1ccf66 From 102c91d7b1a41797ee9533d4a579a6bc3bdd7da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Wed, 17 Dec 2025 14:47:53 +0100 Subject: [PATCH 74/75] Update to 1.26rc1 --- .gitignore | 1 + golang.spec | 32 ++++++++++++++++---------------- sources | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 0c454c2..4541b61 100644 --- a/.gitignore +++ b/.gitignore @@ -174,3 +174,4 @@ /go1.25.3.src.tar.gz /go1.25.4.src.tar.gz /go1.25.5.src.tar.gz +/go1.26rc1.src.tar.gz diff --git a/golang.spec b/golang.spec index 61586c5..ba57da1 100644 --- a/golang.spec +++ b/golang.spec @@ -99,9 +99,9 @@ %endif # Comment out go_prerelease and go_patch as needed -%global go_api 1.25 -#global go_prerelease rc2 -%global go_patch 5 +%global go_api 1.26 +%global go_prerelease rc1 +#global go_patch 1 %global go_version %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease:~%{go_prerelease}} %global go_source %{go_api}%{?go_patch:.%{go_patch}}%{?go_prerelease} @@ -131,20 +131,20 @@ BuildRequires: pcre2-devel, glibc-static, perl-interpreter, procps-ng Provides: go = %{version}-%{release} # Bundled/Vendored provides generated by bundled-deps.sh based on the in tree module data -Provides: bundled(golang(github.com/google/pprof)) = 0.0.0.20250208200701.d0013a598941 -Provides: bundled(golang(github.com/ianlancetaylor/demangle)) = 0.0.0.20240912202439.0a2b6291aafd -Provides: bundled(golang(golang.org/x/arch)) = 0.18.1.0.20250605182141.b2f4e2807dec -Provides: bundled(golang(golang.org/x/build)) = 0.0.0.20250606033421.8c8ff6f34a83 -Provides: bundled(golang(golang.org/x/crypto)) = 0.39.0 -Provides: bundled(golang(golang.org/x/mod)) = 0.25.0 -Provides: bundled(golang(golang.org/x/net)) = 0.41.0 -Provides: bundled(golang(golang.org/x/sync)) = 0.15.0 -Provides: bundled(golang(golang.org/x/sys)) = 0.33.0 -Provides: bundled(golang(golang.org/x/telemetry)) = 0.0.0.20250606142133.60998feb31a8 -Provides: bundled(golang(golang.org/x/term)) = 0.32.0 -Provides: bundled(golang(golang.org/x/text)) = 0.26.0 +Provides: bundled(golang(github.com/google/pprof)) = 0.0.0.20251114195745.4902fdda35c8 +Provides: bundled(golang(github.com/ianlancetaylor/demangle)) = 0.0.0.20250417193237.f615e6bd150b +Provides: bundled(golang(golang.org/x/arch)) = 0.23.0 +Provides: bundled(golang(golang.org/x/build)) = 0.0.0.20251128064159.b9bfd88b30e8 +Provides: bundled(golang(golang.org/x/crypto)) = 0.46.1.0.20251210140736.7dacc380ba00 +Provides: bundled(golang(golang.org/x/mod)) = 0.30.1.0.20251115032019.269c237cf350 +Provides: bundled(golang(golang.org/x/net)) = 0.47.1.0.20251128220604.7c360367ab7e +Provides: bundled(golang(golang.org/x/sync)) = 0.19.0 +Provides: bundled(golang(golang.org/x/sys)) = 0.39.0 +Provides: bundled(golang(golang.org/x/telemetry)) = 0.0.0.20251128220624.abf20d0e57ec +Provides: bundled(golang(golang.org/x/term)) = 0.38.0 +Provides: bundled(golang(golang.org/x/text)) = 0.32.0 Provides: bundled(golang(golang.org/x/tools)) = 0.27.0 -Provides: bundled(golang(golang.org/x/tools)) = 0.34.0 +Provides: bundled(golang(golang.org/x/tools)) = 0.39.1.0.20251205000126.062ef7b6ced2 Provides: bundled(golang(rsc.io/markdown)) = 0.0.0.20240306144322.0bf8f97ee8ef Requires: %{name}-bin = %{version}-%{release} diff --git a/sources b/sources index 6e447e8..dfecfe3 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (go1.25.5.src.tar.gz) = 97ec368521253bce610e1e3a6f10460f4a38eba440289553a40ab27afcdf2bb9b426d150ffaa3be8db50e84a00a4eb723a631ebc4f39168bc133bf7b2f1ccf66 +SHA512 (go1.26rc1.src.tar.gz) = 6696ee765dcde64b830b14e20a5fdf6324916211bff80a62d0db0cbef58bb0856f02e88e95b2f1a3ad6d9282ebd04a377a0b000d56849576caedbd526c9a7923 From 30f6caf69bce62c0317748568e3c82ded2e7feb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20S=C3=A1ez?= Date: Fri, 2 Jan 2026 09:36:58 +0100 Subject: [PATCH 75/75] Update Packit references --- .packit.yaml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.packit.yaml b/.packit.yaml index 78727ca..ab570c5 100644 --- a/.packit.yaml +++ b/.packit.yaml @@ -12,13 +12,6 @@ actions: - bash -c "echo - New release ${PACKIT_PROJECT_VERSION}" jobs: - # Fedora 41 follows Go 1.24 - # https://pagure.io/fesco/issue/3435 - - job: pull_from_upstream - trigger: release - dist_git_branches: fedora-41 - upstream_tag_include: "^go1.24.+" - # Fedora 42 follows Go 1.24 - job: pull_from_upstream trigger: release @@ -35,7 +28,7 @@ jobs: - job: pull_from_upstream trigger: release dist_git_branches: fedora-rawhide - upstream_tag_include: "^go1.25.+" + upstream_tag_include: "^go1.26.+" # Run Koji builds when Packit pull requests are merged - job: koji_build