diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/constants.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/constants.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/constants.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/constants.go 2019-08-17 11:56:26.000000000 +0000 @@ -38,6 +38,7 @@ type JumpTest uint16 // Supported operators for conditional jumps. +// K can be RegX for JumpIfX const ( // K == A JumpEqual JumpTest = iota @@ -134,12 +135,9 @@ opMaskLoadDest = 0x01 opMaskLoadWidth = 0x18 opMaskLoadMode = 0xe0 - // opClsALU - opMaskOperandSrc = 0x08 - opMaskOperator = 0xf0 - // opClsJump - opMaskJumpConst = 0x0f - opMaskJumpCond = 0xf0 + // opClsALU & opClsJump + opMaskOperand = 0x08 + opMaskOperator = 0xf0 ) const ( @@ -192,15 +190,21 @@ opLoadWidth1 ) -// Operator defined by ALUOp* +// Operand for ALU and Jump instructions +type opOperand uint16 +// Supported operand sources. const ( - opALUSrcConstant uint16 = iota << 3 - opALUSrcX + opOperandConstant opOperand = iota << 3 + opOperandX ) +// An jumpOp is a conditional jump condition. +type jumpOp uint16 + +// Supported jump conditions. const ( - opJumpAlways = iota << 4 + opJumpAlways jumpOp = iota << 4 opJumpEqual opJumpGT opJumpGE diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/instructions.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/instructions.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/instructions.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/instructions.go 2019-08-17 11:56:26.000000000 +0000 @@ -89,10 +89,14 @@ case opClsALU: switch op := ALUOp(ri.Op & opMaskOperator); op { case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor: - if ri.Op&opMaskOperandSrc != 0 { + switch operand := opOperand(ri.Op & opMaskOperand); operand { + case opOperandX: return ALUOpX{Op: op} + case opOperandConstant: + return ALUOpConstant{Op: op, Val: ri.K} + default: + return ri } - return ALUOpConstant{Op: op, Val: ri.K} case aluOpNeg: return NegateA{} default: @@ -100,63 +104,18 @@ } case opClsJump: - if ri.Op&opMaskJumpConst != opClsJump { - return ri - } - switch ri.Op & opMaskJumpCond { + switch op := jumpOp(ri.Op & opMaskOperator); op { case opJumpAlways: return Jump{Skip: ri.K} - case opJumpEqual: - if ri.Jt == 0 { - return JumpIf{ - Cond: JumpNotEqual, - Val: ri.K, - SkipTrue: ri.Jf, - SkipFalse: 0, - } - } - return JumpIf{ - Cond: JumpEqual, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, - } - case opJumpGT: - if ri.Jt == 0 { - return JumpIf{ - Cond: JumpLessOrEqual, - Val: ri.K, - SkipTrue: ri.Jf, - SkipFalse: 0, - } - } - return JumpIf{ - Cond: JumpGreaterThan, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, - } - case opJumpGE: - if ri.Jt == 0 { - return JumpIf{ - Cond: JumpLessThan, - Val: ri.K, - SkipTrue: ri.Jf, - SkipFalse: 0, - } - } - return JumpIf{ - Cond: JumpGreaterOrEqual, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, - } - case opJumpSet: - return JumpIf{ - Cond: JumpBitsSet, - Val: ri.K, - SkipTrue: ri.Jt, - SkipFalse: ri.Jf, + case opJumpEqual, opJumpGT, opJumpGE, opJumpSet: + cond, skipTrue, skipFalse := jumpOpToTest(op, ri.Jt, ri.Jf) + switch operand := opOperand(ri.Op & opMaskOperand); operand { + case opOperandX: + return JumpIfX{Cond: cond, SkipTrue: skipTrue, SkipFalse: skipFalse} + case opOperandConstant: + return JumpIf{Cond: cond, Val: ri.K, SkipTrue: skipTrue, SkipFalse: skipFalse} + default: + return ri } default: return ri @@ -187,6 +146,41 @@ } } +func jumpOpToTest(op jumpOp, skipTrue uint8, skipFalse uint8) (JumpTest, uint8, uint8) { + var test JumpTest + + // Decode "fake" jump conditions that don't appear in machine code + // Ensures the Assemble -> Disassemble stage recreates the same instructions + // See https://github.com/golang/go/issues/18470 + if skipTrue == 0 { + switch op { + case opJumpEqual: + test = JumpNotEqual + case opJumpGT: + test = JumpLessOrEqual + case opJumpGE: + test = JumpLessThan + case opJumpSet: + test = JumpBitsNotSet + } + + return test, skipFalse, 0 + } + + switch op { + case opJumpEqual: + test = JumpEqual + case opJumpGT: + test = JumpGreaterThan + case opJumpGE: + test = JumpGreaterOrEqual + case opJumpSet: + test = JumpBitsSet + } + + return test, skipTrue, skipFalse +} + // LoadConstant loads Val into register Dst. type LoadConstant struct { Dst Register @@ -198,7 +192,7 @@ return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadConstant) String() string { switch a.Dst { case RegA: @@ -224,7 +218,7 @@ return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N)) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadScratch) String() string { switch a.Dst { case RegA: @@ -248,7 +242,7 @@ return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadAbsolute) String() string { switch a.Size { case 1: // byte @@ -277,7 +271,7 @@ return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadIndirect) String() string { switch a.Size { case 1: // byte @@ -306,7 +300,7 @@ return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadMemShift) String() string { return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off) } @@ -325,7 +319,7 @@ return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num)) } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a LoadExtension) String() string { switch a.Num { case ExtLen: @@ -392,7 +386,7 @@ }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a StoreScratch) String() string { switch a.Src { case RegA: @@ -413,12 +407,12 @@ // Assemble implements the Instruction Assemble method. func (a ALUOpConstant) Assemble() (RawInstruction, error) { return RawInstruction{ - Op: opClsALU | opALUSrcConstant | uint16(a.Op), + Op: opClsALU | uint16(opOperandConstant) | uint16(a.Op), K: a.Val, }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a ALUOpConstant) String() string { switch a.Op { case ALUOpAdd: @@ -454,11 +448,11 @@ // Assemble implements the Instruction Assemble method. func (a ALUOpX) Assemble() (RawInstruction, error) { return RawInstruction{ - Op: opClsALU | opALUSrcX | uint16(a.Op), + Op: opClsALU | uint16(opOperandX) | uint16(a.Op), }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a ALUOpX) String() string { switch a.Op { case ALUOpAdd: @@ -496,7 +490,7 @@ }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a NegateA) String() string { return fmt.Sprintf("neg") } @@ -509,12 +503,12 @@ // Assemble implements the Instruction Assemble method. func (a Jump) Assemble() (RawInstruction, error) { return RawInstruction{ - Op: opClsJump | opJumpAlways, + Op: opClsJump | uint16(opJumpAlways), K: a.Skip, }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a Jump) String() string { return fmt.Sprintf("ja %d", a.Skip) } @@ -530,11 +524,39 @@ // Assemble implements the Instruction Assemble method. func (a JumpIf) Assemble() (RawInstruction, error) { + return jumpToRaw(a.Cond, opOperandConstant, a.Val, a.SkipTrue, a.SkipFalse) +} + +// String returns the instruction in assembler notation. +func (a JumpIf) String() string { + return jumpToString(a.Cond, fmt.Sprintf("#%d", a.Val), a.SkipTrue, a.SkipFalse) +} + +// JumpIfX skips the following Skip instructions in the program if A +// X is true. +type JumpIfX struct { + Cond JumpTest + SkipTrue uint8 + SkipFalse uint8 +} + +// Assemble implements the Instruction Assemble method. +func (a JumpIfX) Assemble() (RawInstruction, error) { + return jumpToRaw(a.Cond, opOperandX, 0, a.SkipTrue, a.SkipFalse) +} + +// String returns the instruction in assembler notation. +func (a JumpIfX) String() string { + return jumpToString(a.Cond, "x", a.SkipTrue, a.SkipFalse) +} + +// jumpToRaw assembles a jump instruction into a RawInstruction +func jumpToRaw(test JumpTest, operand opOperand, k uint32, skipTrue, skipFalse uint8) (RawInstruction, error) { var ( - cond uint16 + cond jumpOp flip bool ) - switch a.Cond { + switch test { case JumpEqual: cond = opJumpEqual case JumpNotEqual: @@ -552,63 +574,63 @@ case JumpBitsNotSet: cond, flip = opJumpSet, true default: - return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", a.Cond) + return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", test) } - jt, jf := a.SkipTrue, a.SkipFalse + jt, jf := skipTrue, skipFalse if flip { jt, jf = jf, jt } return RawInstruction{ - Op: opClsJump | cond, + Op: opClsJump | uint16(cond) | uint16(operand), Jt: jt, Jf: jf, - K: a.Val, + K: k, }, nil } -// String returns the the instruction in assembler notation. -func (a JumpIf) String() string { - switch a.Cond { +// jumpToString converts a jump instruction to assembler notation +func jumpToString(cond JumpTest, operand string, skipTrue, skipFalse uint8) string { + switch cond { // K == A case JumpEqual: - return conditionalJump(a, "jeq", "jneq") + return conditionalJump(operand, skipTrue, skipFalse, "jeq", "jneq") // K != A case JumpNotEqual: - return fmt.Sprintf("jneq #%d,%d", a.Val, a.SkipTrue) + return fmt.Sprintf("jneq %s,%d", operand, skipTrue) // K > A case JumpGreaterThan: - return conditionalJump(a, "jgt", "jle") + return conditionalJump(operand, skipTrue, skipFalse, "jgt", "jle") // K < A case JumpLessThan: - return fmt.Sprintf("jlt #%d,%d", a.Val, a.SkipTrue) + return fmt.Sprintf("jlt %s,%d", operand, skipTrue) // K >= A case JumpGreaterOrEqual: - return conditionalJump(a, "jge", "jlt") + return conditionalJump(operand, skipTrue, skipFalse, "jge", "jlt") // K <= A case JumpLessOrEqual: - return fmt.Sprintf("jle #%d,%d", a.Val, a.SkipTrue) + return fmt.Sprintf("jle %s,%d", operand, skipTrue) // K & A != 0 case JumpBitsSet: - if a.SkipFalse > 0 { - return fmt.Sprintf("jset #%d,%d,%d", a.Val, a.SkipTrue, a.SkipFalse) + if skipFalse > 0 { + return fmt.Sprintf("jset %s,%d,%d", operand, skipTrue, skipFalse) } - return fmt.Sprintf("jset #%d,%d", a.Val, a.SkipTrue) + return fmt.Sprintf("jset %s,%d", operand, skipTrue) // K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips case JumpBitsNotSet: - return JumpIf{Cond: JumpBitsSet, SkipTrue: a.SkipFalse, SkipFalse: a.SkipTrue, Val: a.Val}.String() + return jumpToString(JumpBitsSet, operand, skipFalse, skipTrue) default: - return fmt.Sprintf("unknown instruction: %#v", a) + return fmt.Sprintf("unknown JumpTest %#v", cond) } } -func conditionalJump(inst JumpIf, positiveJump, negativeJump string) string { - if inst.SkipTrue > 0 { - if inst.SkipFalse > 0 { - return fmt.Sprintf("%s #%d,%d,%d", positiveJump, inst.Val, inst.SkipTrue, inst.SkipFalse) +func conditionalJump(operand string, skipTrue, skipFalse uint8, positiveJump, negativeJump string) string { + if skipTrue > 0 { + if skipFalse > 0 { + return fmt.Sprintf("%s %s,%d,%d", positiveJump, operand, skipTrue, skipFalse) } - return fmt.Sprintf("%s #%d,%d", positiveJump, inst.Val, inst.SkipTrue) + return fmt.Sprintf("%s %s,%d", positiveJump, operand, skipTrue) } - return fmt.Sprintf("%s #%d,%d", negativeJump, inst.Val, inst.SkipFalse) + return fmt.Sprintf("%s %s,%d", negativeJump, operand, skipFalse) } // RetA exits the BPF program, returning the value of register A. @@ -621,7 +643,7 @@ }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a RetA) String() string { return fmt.Sprintf("ret a") } @@ -639,7 +661,7 @@ }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a RetConstant) String() string { return fmt.Sprintf("ret #%d", a.Val) } @@ -654,7 +676,7 @@ }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a TXA) String() string { return fmt.Sprintf("txa") } @@ -669,7 +691,7 @@ }, nil } -// String returns the the instruction in assembler notation. +// String returns the instruction in assembler notation. func (a TAX) String() string { return fmt.Sprintf("tax") } diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/instructions_test.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/instructions_test.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/instructions_test.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/instructions_test.go 2019-08-17 11:56:26.000000000 +0000 @@ -64,14 +64,22 @@ NegateA{}, - Jump{Skip: 10}, - JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 8, SkipFalse: 9}, - JumpIf{Cond: JumpNotEqual, Val: 42, SkipTrue: 8}, - JumpIf{Cond: JumpLessThan, Val: 42, SkipTrue: 7}, - JumpIf{Cond: JumpLessOrEqual, Val: 42, SkipTrue: 6}, - JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 4, SkipFalse: 5}, - JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 3, SkipFalse: 4}, - JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 2, SkipFalse: 3}, + Jump{Skip: 17}, + JumpIf{Cond: JumpEqual, Val: 42, SkipTrue: 15, SkipFalse: 16}, + JumpIf{Cond: JumpNotEqual, Val: 42, SkipTrue: 15}, + JumpIf{Cond: JumpLessThan, Val: 42, SkipTrue: 14}, + JumpIf{Cond: JumpLessOrEqual, Val: 42, SkipTrue: 13}, + JumpIf{Cond: JumpGreaterThan, Val: 42, SkipTrue: 11, SkipFalse: 12}, + JumpIf{Cond: JumpGreaterOrEqual, Val: 42, SkipTrue: 10, SkipFalse: 11}, + JumpIf{Cond: JumpBitsSet, Val: 42, SkipTrue: 9, SkipFalse: 10}, + + JumpIfX{Cond: JumpEqual, SkipTrue: 8, SkipFalse: 9}, + JumpIfX{Cond: JumpNotEqual, SkipTrue: 8}, + JumpIfX{Cond: JumpLessThan, SkipTrue: 7}, + JumpIfX{Cond: JumpLessOrEqual, SkipTrue: 6}, + JumpIfX{Cond: JumpGreaterThan, SkipTrue: 4, SkipFalse: 5}, + JumpIfX{Cond: JumpGreaterOrEqual, SkipTrue: 3, SkipFalse: 4}, + JumpIfX{Cond: JumpBitsSet, SkipTrue: 2, SkipFalse: 3}, TAX{}, TXA{}, @@ -487,7 +495,67 @@ }, { instruction: JumpIf{Cond: 0xffff, Val: 42, SkipTrue: 1, SkipFalse: 2}, - assembler: "unknown instruction: bpf.JumpIf{Cond:0xffff, Val:0x2a, SkipTrue:0x1, SkipFalse:0x2}", + assembler: "unknown JumpTest 0xffff", + }, + { + instruction: JumpIfX{Cond: JumpEqual, SkipTrue: 8, SkipFalse: 9}, + assembler: "jeq x,8,9", + }, + { + instruction: JumpIfX{Cond: JumpEqual, SkipTrue: 8}, + assembler: "jeq x,8", + }, + { + instruction: JumpIfX{Cond: JumpEqual, SkipFalse: 8}, + assembler: "jneq x,8", + }, + { + instruction: JumpIfX{Cond: JumpNotEqual, SkipTrue: 8}, + assembler: "jneq x,8", + }, + { + instruction: JumpIfX{Cond: JumpLessThan, SkipTrue: 7}, + assembler: "jlt x,7", + }, + { + instruction: JumpIfX{Cond: JumpLessOrEqual, SkipTrue: 6}, + assembler: "jle x,6", + }, + { + instruction: JumpIfX{Cond: JumpGreaterThan, SkipTrue: 4, SkipFalse: 5}, + assembler: "jgt x,4,5", + }, + { + instruction: JumpIfX{Cond: JumpGreaterThan, SkipTrue: 4}, + assembler: "jgt x,4", + }, + { + instruction: JumpIfX{Cond: JumpGreaterOrEqual, SkipTrue: 3, SkipFalse: 4}, + assembler: "jge x,3,4", + }, + { + instruction: JumpIfX{Cond: JumpGreaterOrEqual, SkipTrue: 3}, + assembler: "jge x,3", + }, + { + instruction: JumpIfX{Cond: JumpBitsSet, SkipTrue: 2, SkipFalse: 3}, + assembler: "jset x,2,3", + }, + { + instruction: JumpIfX{Cond: JumpBitsSet, SkipTrue: 2}, + assembler: "jset x,2", + }, + { + instruction: JumpIfX{Cond: JumpBitsNotSet, SkipTrue: 2, SkipFalse: 3}, + assembler: "jset x,3,2", + }, + { + instruction: JumpIfX{Cond: JumpBitsNotSet, SkipTrue: 2}, + assembler: "jset x,0,2", + }, + { + instruction: JumpIfX{Cond: 0xffff, SkipTrue: 1, SkipFalse: 2}, + assembler: "unknown JumpTest 0xffff", }, { instruction: TAX{}, diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/testdata/all_instructions.bpf golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/testdata/all_instructions.bpf --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/testdata/all_instructions.bpf 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/testdata/all_instructions.bpf 2019-08-17 11:56:26.000000000 +0000 @@ -1 +1 @@ -50,0 0 0 42,1 0 0 42,96 0 0 3,97 0 0 3,48 0 0 42,40 0 0 42,32 0 0 42,80 0 0 42,72 0 0 42,64 0 0 42,177 0 0 42,128 0 0 0,32 0 0 4294963200,32 0 0 4294963204,32 0 0 4294963256,2 0 0 3,3 0 0 3,4 0 0 42,20 0 0 42,36 0 0 42,52 0 0 42,68 0 0 42,84 0 0 42,100 0 0 42,116 0 0 42,148 0 0 42,164 0 0 42,12 0 0 0,28 0 0 0,44 0 0 0,60 0 0 0,76 0 0 0,92 0 0 0,108 0 0 0,124 0 0 0,156 0 0 0,172 0 0 0,132 0 0 0,5 0 0 10,21 8 9 42,21 0 8 42,53 0 7 42,37 0 6 42,37 4 5 42,53 3 4 42,69 2 3 42,7 0 0 0,135 0 0 0,22 0 0 0,6 0 0 0, +57,0 0 0 42,1 0 0 42,96 0 0 3,97 0 0 3,48 0 0 42,40 0 0 42,32 0 0 42,80 0 0 42,72 0 0 42,64 0 0 42,177 0 0 42,128 0 0 0,32 0 0 4294963200,32 0 0 4294963204,32 0 0 4294963256,2 0 0 3,3 0 0 3,4 0 0 42,20 0 0 42,36 0 0 42,52 0 0 42,68 0 0 42,84 0 0 42,100 0 0 42,116 0 0 42,148 0 0 42,164 0 0 42,12 0 0 0,28 0 0 0,44 0 0 0,60 0 0 0,76 0 0 0,92 0 0 0,108 0 0 0,124 0 0 0,156 0 0 0,172 0 0 0,132 0 0 0,5 0 0 17,21 15 16 42,21 0 15 42,53 0 14 42,37 0 13 42,37 11 12 42,53 10 11 42,69 9 10 42,29 8 9 0,29 0 8 0,61 0 7 0,45 0 6 0,45 4 5 0,61 3 4 0,77 2 3 0,7 0 0 0,135 0 0 0,22 0 0 0,6 0 0 42, diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/testdata/all_instructions.txt golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/testdata/all_instructions.txt --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/testdata/all_instructions.txt 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/testdata/all_instructions.txt 2019-08-17 11:56:26.000000000 +0000 @@ -1,6 +1,6 @@ # This filter is compiled to all_instructions.bpf by the `bpf_asm` # tool, which can be found in the linux kernel source tree under -# tools/net. +# tools/bpf. # Load immediate ld #42 @@ -60,7 +60,7 @@ # !A neg -# Jumps +# Jump A constant ja end jeq #42,prev,end jne #42,end @@ -70,6 +70,15 @@ jge #42,prev,end jset #42,prev,end +# Jump A X +jeq x,prev,end +jne x,end +jlt x,end +jle x,end +jgt x,prev,end +jge x,prev,end +jset x,prev,end + # Register transfers tax txa diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/vm_bpf_test.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/vm_bpf_test.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/vm_bpf_test.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/vm_bpf_test.go 2019-08-17 11:56:26.000000000 +0000 @@ -12,6 +12,8 @@ "golang.org/x/net/bpf" "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" + "golang.org/x/net/nettest" ) // A virtualMachine is a BPF virtual machine which can process an @@ -137,7 +139,7 @@ // testOSVM creates a virtualMachine which uses the OS's BPF VM by injecting // packets into a UDP listener with a BPF program attached to it. func testOSVM(t *testing.T, filter []bpf.Instruction) (virtualMachine, func()) { - l, err := net.ListenPacket("udp4", "127.0.0.1:0") + l, err := nettest.NewLocalPacketListener("udp") if err != nil { t.Fatalf("failed to open OS VM UDP listener: %v", err) } @@ -147,12 +149,17 @@ t.Fatalf("failed to compile BPF program: %v", err) } - p := ipv4.NewPacketConn(l) - if err = p.SetBPF(prog); err != nil { + ip := l.LocalAddr().(*net.UDPAddr).IP + if ip.To4() != nil && ip.To16() == nil { + err = ipv4.NewPacketConn(l).SetBPF(prog) + } else { + err = ipv6.NewPacketConn(l).SetBPF(prog) + } + if err != nil { t.Fatalf("failed to attach BPF program to listener: %v", err) } - s, err := net.Dial("udp4", l.LocalAddr().String()) + s, err := net.Dial(l.LocalAddr().Network(), l.LocalAddr().String()) if err != nil { t.Fatalf("failed to dial connection to listener: %v", err) } diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/vm.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/vm.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/vm.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/vm.go 2019-08-17 11:56:26.000000000 +0000 @@ -35,6 +35,13 @@ if check <= int(ins.SkipFalse) { return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse) } + case JumpIfX: + if check <= int(ins.SkipTrue) { + return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue) + } + if check <= int(ins.SkipFalse) { + return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse) + } // Check for division or modulus by zero case ALUOpConstant: if ins.Val != 0 { @@ -109,6 +116,9 @@ case JumpIf: jump := jumpIf(ins, regA) i += jump + case JumpIfX: + jump := jumpIfX(ins, regA, regX) + i += jump case LoadAbsolute: regA, ok = loadAbsolute(ins, in) case LoadConstant: diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/vm_instructions.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/vm_instructions.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/vm_instructions.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/vm_instructions.go 2019-08-17 11:56:26.000000000 +0000 @@ -55,34 +55,41 @@ } } -func jumpIf(ins JumpIf, value uint32) int { +func jumpIf(ins JumpIf, regA uint32) int { + return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, ins.Val) +} + +func jumpIfX(ins JumpIfX, regA uint32, regX uint32) int { + return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, regX) +} + +func jumpIfCommon(cond JumpTest, skipTrue, skipFalse uint8, regA uint32, value uint32) int { var ok bool - inV := uint32(ins.Val) - switch ins.Cond { + switch cond { case JumpEqual: - ok = value == inV + ok = regA == value case JumpNotEqual: - ok = value != inV + ok = regA != value case JumpGreaterThan: - ok = value > inV + ok = regA > value case JumpLessThan: - ok = value < inV + ok = regA < value case JumpGreaterOrEqual: - ok = value >= inV + ok = regA >= value case JumpLessOrEqual: - ok = value <= inV + ok = regA <= value case JumpBitsSet: - ok = (value & inV) != 0 + ok = (regA & value) != 0 case JumpBitsNotSet: - ok = (value & inV) == 0 + ok = (regA & value) == 0 } if ok { - return int(ins.SkipTrue) + return int(skipTrue) } - return int(ins.SkipFalse) + return int(skipFalse) } func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) { @@ -122,7 +129,8 @@ func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) { offset := int(ins.Off) - if !inBounds(len(in), offset, 0) { + // Size of LoadMemShift is always 1 byte + if !inBounds(len(in), offset, 1) { return 0, false } diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/vm_jump_test.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/vm_jump_test.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/vm_jump_test.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/vm_jump_test.go 2019-08-17 11:56:26.000000000 +0000 @@ -83,6 +83,32 @@ } } +func TestVMJumpIfXTrueOutOfProgram(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.JumpIfX{ + Cond: bpf.JumpEqual, + SkipTrue: 2, + }, + bpf.RetA{}, + }) + if errStr(err) != "cannot jump 2 instructions in true case; jumping past program bounds" { + t.Fatalf("unexpected error: %v", err) + } +} + +func TestVMJumpIfXFalseOutOfProgram(t *testing.T) { + _, _, err := testVM(t, []bpf.Instruction{ + bpf.JumpIfX{ + Cond: bpf.JumpEqual, + SkipFalse: 3, + }, + bpf.RetA{}, + }) + if errStr(err) != "cannot jump 3 instructions in false case; jumping past program bounds" { + t.Fatalf("unexpected error: %v", err) + } +} + func TestVMJumpIfEqual(t *testing.T) { vm, done, err := testVM(t, []bpf.Instruction{ bpf.LoadAbsolute{ @@ -354,6 +380,326 @@ SkipTrue: 1, }, bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 10, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x01, 0x02, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 2, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfXEqual(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.LoadConstant{ + Dst: bpf.RegX, + Val: 1, + }, + bpf.JumpIfX{ + Cond: bpf.JumpEqual, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 9, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 1, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfXNotEqual(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 1, + }, + bpf.LoadConstant{ + Dst: bpf.RegX, + Val: 1, + }, + bpf.JumpIfX{ + Cond: bpf.JumpNotEqual, + SkipFalse: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 9, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 1, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 1, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfXGreaterThan(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 4, + }, + bpf.LoadConstant{ + Dst: bpf.RegX, + Val: 0x00010202, + }, + bpf.JumpIfX{ + Cond: bpf.JumpGreaterThan, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 12, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 4, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfXLessThan(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 4, + }, + bpf.LoadConstant{ + Dst: bpf.RegX, + Val: 0xff010203, + }, + bpf.JumpIfX{ + Cond: bpf.JumpLessThan, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 12, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 4, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfXGreaterOrEqual(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 4, + }, + bpf.LoadConstant{ + Dst: bpf.RegX, + Val: 0x00010203, + }, + bpf.JumpIfX{ + Cond: bpf.JumpGreaterOrEqual, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 12, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 4, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfXLessOrEqual(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 4, + }, + bpf.LoadConstant{ + Dst: bpf.RegX, + Val: 0xff010203, + }, + bpf.JumpIfX{ + Cond: bpf.JumpLessOrEqual, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 12, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 4, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfXBitsSet(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 2, + }, + bpf.LoadConstant{ + Dst: bpf.RegX, + Val: 0x1122, + }, + bpf.JumpIfX{ + Cond: bpf.JumpBitsSet, + SkipTrue: 1, + }, + bpf.RetConstant{ + Val: 0, + }, + bpf.RetConstant{ + Val: 10, + }, + }) + if err != nil { + t.Fatalf("failed to load BPF program: %v", err) + } + defer done() + + out, err := vm.Run([]byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x01, 0x02, + }) + if err != nil { + t.Fatalf("unexpected error while running program: %v", err) + } + if want, got := 2, out; want != got { + t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + want, got) + } +} + +func TestVMJumpIfXBitsNotSet(t *testing.T) { + vm, done, err := testVM(t, []bpf.Instruction{ + bpf.LoadAbsolute{ + Off: 8, + Size: 2, + }, + bpf.LoadConstant{ + Dst: bpf.RegX, + Val: 0x1221, + }, + bpf.JumpIfX{ + Cond: bpf.JumpBitsNotSet, + SkipTrue: 1, + }, + bpf.RetConstant{ Val: 0, }, bpf.RetConstant{ diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/vm_load_test.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/vm_load_test.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/bpf/vm_load_test.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/bpf/vm_load_test.go 2019-08-17 11:56:26.000000000 +0000 @@ -13,55 +13,61 @@ ) func TestVMLoadAbsoluteOffsetOutOfBounds(t *testing.T) { + pkt := []byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, + } + vm, done, err := testVM(t, []bpf.Instruction{ bpf.LoadAbsolute{ - Off: 100, - Size: 2, + Off: uint32(len(pkt)), + Size: 1, }, - bpf.RetA{}, + // Out of bounds should return 0, return 1 to tell if execution continued + bpf.RetConstant{Val: 1}, }) if err != nil { t.Fatalf("failed to load BPF program: %v", err) } defer done() - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, 1, 2, 3, - }) + out, err := vm.Run(pkt) if err != nil { t.Fatalf("unexpected error while running program: %v", err) } if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + t.Fatalf("unexpected result:\n- want: %d\n- got: %d", want, got) } } func TestVMLoadAbsoluteOffsetPlusSizeOutOfBounds(t *testing.T) { + pkt := []byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, + } + vm, done, err := testVM(t, []bpf.Instruction{ bpf.LoadAbsolute{ - Off: 8, + Off: uint32(len(pkt) - 1), Size: 2, }, - bpf.RetA{}, + // Out of bounds should return 0, return 1 to tell if execution continued + bpf.RetConstant{Val: 1}, }) if err != nil { t.Fatalf("failed to load BPF program: %v", err) } defer done() - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, - }) + out, err := vm.Run(pkt) if err != nil { t.Fatalf("unexpected error while running program: %v", err) } if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + t.Fatalf("unexpected result:\n- want: %d\n- got: %d", want, got) } } @@ -107,54 +113,60 @@ } func TestVMLoadIndirectOutOfBounds(t *testing.T) { + pkt := []byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, + } + vm, done, err := testVM(t, []bpf.Instruction{ bpf.LoadIndirect{ - Off: 100, + Off: uint32(len(pkt)), Size: 1, }, - bpf.RetA{}, + // Out of bounds should return 0, return 1 to tell if execution continued + bpf.RetConstant{Val: 1}, }) if err != nil { t.Fatalf("failed to load BPF program: %v", err) } defer done() - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, - }) + out, err := vm.Run(pkt) if err != nil { t.Fatalf("unexpected error while running program: %v", err) } if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + t.Fatalf("unexpected result:\n- want: %d\n- got: %d", want, got) } } func TestVMLoadMemShiftOutOfBounds(t *testing.T) { + pkt := []byte{ + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0, + } + vm, done, err := testVM(t, []bpf.Instruction{ bpf.LoadMemShift{ - Off: 100, + Off: uint32(len(pkt)), }, - bpf.RetA{}, + // Out of bounds should return 0, return 1 to tell if execution continued + bpf.RetConstant{Val: 1}, }) if err != nil { t.Fatalf("failed to load BPF program: %v", err) } defer done() - out, err := vm.Run([]byte{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0, - }) + out, err := vm.Run(pkt) if err != nil { t.Fatalf("unexpected error while running program: %v", err) } if want, got := 0, out; want != got { - t.Fatalf("unexpected number of output bytes:\n- want: %d\n- got: %d", + t.Fatalf("unexpected result:\n- want: %d\n- got: %d", want, got) } } diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/context/ctxhttp/ctxhttp_17_test.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/context/ctxhttp/ctxhttp_17_test.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/context/ctxhttp/ctxhttp_17_test.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/context/ctxhttp/ctxhttp_17_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -// Copyright 2015 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. - -// +build !plan9,go1.7 - -package ctxhttp - -import ( - "io" - "net/http" - "net/http/httptest" - "testing" - - "context" -) - -func TestGo17Context(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, "ok") - })) - defer ts.Close() - ctx := context.Background() - resp, err := Get(ctx, http.DefaultClient, ts.URL) - if resp == nil || err != nil { - t.Fatalf("error received from client: %v %v", err, resp) - } - resp.Body.Close() -} diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/context/ctxhttp/ctxhttp.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/context/ctxhttp/ctxhttp.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/context/ctxhttp/ctxhttp.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/context/ctxhttp/ctxhttp.go 2019-08-17 11:56:26.000000000 +0000 @@ -2,18 +2,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build go1.7 - // Package ctxhttp provides helper functions for performing context-aware HTTP requests. package ctxhttp // import "golang.org/x/net/context/ctxhttp" import ( + "context" "io" "net/http" "net/url" "strings" - - "golang.org/x/net/context" ) // Do sends an HTTP request with the provided http.Client and returns diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/context/ctxhttp/ctxhttp_pre17.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/context/ctxhttp/ctxhttp_pre17.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/context/ctxhttp/ctxhttp_pre17.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/context/ctxhttp/ctxhttp_pre17.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,147 +0,0 @@ -// Copyright 2015 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. - -// +build !go1.7 - -package ctxhttp // import "golang.org/x/net/context/ctxhttp" - -import ( - "io" - "net/http" - "net/url" - "strings" - - "golang.org/x/net/context" -) - -func nop() {} - -var ( - testHookContextDoneBeforeHeaders = nop - testHookDoReturned = nop - testHookDidBodyClose = nop -) - -// Do sends an HTTP request with the provided http.Client and returns an HTTP response. -// If the client is nil, http.DefaultClient is used. -// If the context is canceled or times out, ctx.Err() will be returned. -func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { - if client == nil { - client = http.DefaultClient - } - - // TODO(djd): Respect any existing value of req.Cancel. - cancel := make(chan struct{}) - req.Cancel = cancel - - type responseAndError struct { - resp *http.Response - err error - } - result := make(chan responseAndError, 1) - - // Make local copies of test hooks closed over by goroutines below. - // Prevents data races in tests. - testHookDoReturned := testHookDoReturned - testHookDidBodyClose := testHookDidBodyClose - - go func() { - resp, err := client.Do(req) - testHookDoReturned() - result <- responseAndError{resp, err} - }() - - var resp *http.Response - - select { - case <-ctx.Done(): - testHookContextDoneBeforeHeaders() - close(cancel) - // Clean up after the goroutine calling client.Do: - go func() { - if r := <-result; r.resp != nil { - testHookDidBodyClose() - r.resp.Body.Close() - } - }() - return nil, ctx.Err() - case r := <-result: - var err error - resp, err = r.resp, r.err - if err != nil { - return resp, err - } - } - - c := make(chan struct{}) - go func() { - select { - case <-ctx.Done(): - close(cancel) - case <-c: - // The response's Body is closed. - } - }() - resp.Body = ¬ifyingReader{resp.Body, c} - - return resp, nil -} - -// Get issues a GET request via the Do function. -func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return nil, err - } - return Do(ctx, client, req) -} - -// Head issues a HEAD request via the Do function. -func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { - req, err := http.NewRequest("HEAD", url, nil) - if err != nil { - return nil, err - } - return Do(ctx, client, req) -} - -// Post issues a POST request via the Do function. -func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest("POST", url, body) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", bodyType) - return Do(ctx, client, req) -} - -// PostForm issues a POST request via the Do function. -func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { - return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) -} - -// notifyingReader is an io.ReadCloser that closes the notify channel after -// Close is called or a Read fails on the underlying ReadCloser. -type notifyingReader struct { - io.ReadCloser - notify chan<- struct{} -} - -func (r *notifyingReader) Read(p []byte) (int, error) { - n, err := r.ReadCloser.Read(p) - if err != nil && r.notify != nil { - close(r.notify) - r.notify = nil - } - return n, err -} - -func (r *notifyingReader) Close() error { - err := r.ReadCloser.Close() - if r.notify != nil { - close(r.notify) - r.notify = nil - } - return err -} diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/context/ctxhttp/ctxhttp_pre17_test.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/context/ctxhttp/ctxhttp_pre17_test.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/context/ctxhttp/ctxhttp_pre17_test.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/context/ctxhttp/ctxhttp_pre17_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -// Copyright 2015 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. - -// +build !plan9,!go1.7 - -package ctxhttp - -import ( - "net" - "net/http" - "net/http/httptest" - "sync" - "testing" - "time" - - "golang.org/x/net/context" -) - -// golang.org/issue/14065 -func TestClosesResponseBodyOnCancel(t *testing.T) { - defer func() { testHookContextDoneBeforeHeaders = nop }() - defer func() { testHookDoReturned = nop }() - defer func() { testHookDidBodyClose = nop }() - - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) - defer ts.Close() - - ctx, cancel := context.WithCancel(context.Background()) - - // closed when Do enters select case <-ctx.Done() - enteredDonePath := make(chan struct{}) - - testHookContextDoneBeforeHeaders = func() { - close(enteredDonePath) - } - - testHookDoReturned = func() { - // We now have the result (the Flush'd headers) at least, - // so we can cancel the request. - cancel() - - // But block the client.Do goroutine from sending - // until Do enters into the <-ctx.Done() path, since - // otherwise if both channels are readable, select - // picks a random one. - <-enteredDonePath - } - - sawBodyClose := make(chan struct{}) - testHookDidBodyClose = func() { close(sawBodyClose) } - - tr := &http.Transport{} - defer tr.CloseIdleConnections() - c := &http.Client{Transport: tr} - req, _ := http.NewRequest("GET", ts.URL, nil) - _, doErr := Do(ctx, c, req) - - select { - case <-sawBodyClose: - case <-time.After(5 * time.Second): - t.Fatal("timeout waiting for body to close") - } - - if doErr != ctx.Err() { - t.Errorf("Do error = %v; want %v", doErr, ctx.Err()) - } -} - -type noteCloseConn struct { - net.Conn - onceClose sync.Once - closefn func() -} - -func (c *noteCloseConn) Close() error { - c.onceClose.Do(c.closefn) - return c.Conn.Close() -} diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/context/ctxhttp/ctxhttp_test.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/context/ctxhttp/ctxhttp_test.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/context/ctxhttp/ctxhttp_test.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/context/ctxhttp/ctxhttp_test.go 2019-08-17 11:56:26.000000000 +0000 @@ -7,16 +7,28 @@ package ctxhttp import ( + "context" "io" "io/ioutil" "net/http" "net/http/httptest" "testing" "time" - - "golang.org/x/net/context" ) +func TestGo17Context(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "ok") + })) + defer ts.Close() + ctx := context.Background() + resp, err := Get(ctx, http.DefaultClient, ts.URL) + if resp == nil || err != nil { + t.Fatalf("error received from client: %v %v", err, resp) + } + resp.Body.Close() +} + const ( requestDuration = 100 * time.Millisecond requestBody = "ok" diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/CONTRIBUTING.md golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/CONTRIBUTING.md --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/CONTRIBUTING.md 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/CONTRIBUTING.md 2019-08-17 11:56:26.000000000 +0000 @@ -4,16 +4,15 @@ It is the work of hundreds of contributors. We appreciate your help! - ## Filing issues When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. The gophers there will answer or ask you to file an issue if you've tripped over a bug. @@ -23,9 +22,5 @@ Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) before sending patches. -**We do not accept GitHub pull requests** -(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). - Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file. - diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/changelog golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/changelog --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/changelog 2018-07-09 05:02:13.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/changelog 2019-08-17 12:02:42.000000000 +0000 @@ -1,3 +1,56 @@ +golang-golang-x-net-dev (1:0.0+git20190811.74dc4d7+dfsg-1) unstable; urgency=high + + * Team upload. + * New upstream version 0.0+git20190811.74dc4d7+dfsg + - Include fixes for CVE-2019-9512 and CVE-2019-9514 + + -- Dr. Tobias Quathamer Sat, 17 Aug 2019 14:02:42 +0200 + +golang-golang-x-net-dev (1:0.0+git20190724.ca1201d+dfsg-1) unstable; urgency=medium + + [ Drew Parsons ] + * add debian/watch + + [ Anthony Fok ] + * Update debian/watch to handle +dfsg suffix + * Remove Lintian override debian-watch-file-is-missing + * Apply "cme fix dpkg" fixes: + - Specify compatibility level with "Build-Depends: debhelper-compat (= 12)" + - Bump Standards-Version to 4.4.0 (no change) + * Remove security patches that are contained in this new upstream version, + namely, CVE-2018-17846 and CVE-2018-17847_CVE-2018-17848. + * Update dependencies according to go.mod: Rename golang-x-text-dev to + golang-golang-x-text-dev, and add golang-golang-x-sys-dev + + -- Anthony Fok Sun, 28 Jul 2019 02:08:05 -0600 + +golang-golang-x-net-dev (1:0.0+git20181201.351d144+dfsg-3) unstable; urgency=medium + + * Team upload. + * Apply security patches (upstream commits). Closes: #911795. + - CVE-2018-17846: commit d26f9f9a57f3fab6a695bec0d84433c2c50f8bbf + - CVE-2018-17847, CVE-2018-17848: + commit 4b62a64f59f73840b9ab79204c94fee61cd1ba2c + + -- Drew Parsons Tue, 30 Apr 2019 16:42:08 +0800 + +golang-golang-x-net-dev (1:0.0+git20181201.351d144+dfsg-2) unstable; urgency=medium + + * Remove obsolete patch for s390. Closes: #916236. + + -- Martín Ferrari Fri, 14 Dec 2018 13:56:28 +0000 + +golang-golang-x-net-dev (1:0.0+git20181201.351d144+dfsg-1) unstable; urgency=medium + + * Team upload. + * New upstream version 0.0+git20181201.351d144+dfsg + - Refresh patch + * Use debhelper v11 + * Update team name + * Update to Standards-Version 4.2.1 + + -- Dr. Tobias Quathamer Wed, 05 Dec 2018 20:49:06 +0100 + golang-golang-x-net-dev (1:0.0+git20180124.0ed95ab+dfsg-2) unstable; urgency=medium * Team upload. diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/compat golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/compat --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/compat 2018-07-09 02:33:49.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -9 diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/control golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/control --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/control 2018-07-09 02:33:49.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/control 2019-08-17 12:00:23.000000000 +0000 @@ -1,19 +1,20 @@ # XXX: This source package should be called golang-golang-x-net, the -dev # suffix is a mistake. --stapelberg Source: golang-golang-x-net-dev -Maintainer: Debian Go packaging team +Maintainer: Debian Go Packaging Team Uploaders: Martín Ferrari , Michael Stapelberg , Tim Potter , - Anthony Fok , + Anthony Fok Section: devel Testsuite: autopkgtest-pkg-go Priority: optional -Build-Depends: debhelper (>= 9), - dh-golang (>= 1.17), +Build-Depends: debhelper-compat (= 12), + dh-golang (>= 1.31~), golang-any, - golang-x-text-dev, -Standards-Version: 4.1.3 + golang-golang-x-sys-dev (>= 0.0~git20190215.d0b11bd~), + golang-golang-x-text-dev (>= 0.3.0~) +Standards-Version: 4.4.0 Vcs-Browser: https://salsa.debian.org/go-team/packages/golang-go.net Vcs-Git: https://salsa.debian.org/go-team/packages/golang-go.net.git Homepage: https://godoc.org/golang.org/x/net @@ -21,12 +22,13 @@ Package: golang-golang-x-net-dev Architecture: all -Depends: golang-x-text-dev, +Depends: golang-golang-x-sys-dev (>= 0.0~git20190215.d0b11bd~), + golang-golang-x-text-dev (>= 0.3.0~), ${misc:Depends}, - ${shlibs:Depends}, -Breaks: golang-go.net-dev (<< 0.0+git20150226.3d87fd6-2~), -Provides: golang-go.net-dev, -Replaces: golang-go.net-dev (<< 0.0+git20150226.3d87fd6-2~), + ${shlibs:Depends} +Breaks: golang-go.net-dev (<< 0.0+git20150226.3d87fd6-2~) +Provides: golang-go.net-dev +Replaces: golang-go.net-dev (<< 0.0+git20150226.3d87fd6-2~) Description: Supplementary Go networking libraries Supplementary Go networking libraries (golang.org/x/net) not included in the main distribution: @@ -71,7 +73,7 @@ Architecture: all Section: oldlibs Depends: golang-golang-x-net-dev, - ${misc:Depends}, + ${misc:Depends} Description: Transitional package for golang-golang-x-net-dev This is a transitional package to ease upgrades to the golang-golang-x-net-dev package. It can safely be removed. diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/gbp.conf golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/gbp.conf --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/gbp.conf 2018-07-09 02:33:49.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/gbp.conf 2019-08-17 12:00:23.000000000 +0000 @@ -1,5 +1,7 @@ [DEFAULT] debian-branch = debian/sid +upstream-branch = repackaged +pristine-tar = False [buildpackage] dist = DEP14 diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/patches/01-Fix_s390x_build.patch golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/patches/01-Fix_s390x_build.patch --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/patches/01-Fix_s390x_build.patch 2018-07-09 02:33:49.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/patches/01-Fix_s390x_build.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -Description: This package does not buildon s390x/gccgo, due to a missing header - file in gccgo. Use the generic routines instead. ---- a/internal/socket/sys_linux.go -+++ b/internal/socket/sys_linux.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. - --// +build linux,!s390x,!386 -+// +build linux,!386 - - package socket - ---- a/internal/socket/sys_linux_s390x.go -+++ b/internal/socket/sys_linux_s390x.go -@@ -4,12 +4,14 @@ - - package socket - -+/* - import ( - "syscall" - "unsafe" - ) - - func probeProtocolStack() int { return 8 } -+*/ - - const ( - sysSETSOCKOPT = 0xe -@@ -20,6 +22,7 @@ - sysSENDMMSG = 0x14 - ) - -+/* - func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno) - func rawsocketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall.Errno) - -@@ -53,3 +56,4 @@ - n, errno := socketcall(sysSENDMMSG, s, uintptr(unsafe.Pointer(&hs[0])), uintptr(len(hs)), uintptr(flags), 0, 0) - return int(n), errnoErr(errno) - } -+*/ ---- a/internal/socket/sys_linux_s390x.s -+++ b/internal/socket/sys_linux_s390x.s -@@ -2,6 +2,8 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - -+// +build ignore -+ - #include "textflag.h" - - TEXT ·socketcall(SB),NOSPLIT,$0-72 ---- a/internal/socket/sys_unix.go -+++ b/internal/socket/sys_unix.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. - --// +build darwin dragonfly freebsd linux,!s390x,!386 netbsd openbsd -+// +build darwin dragonfly freebsd linux,!386 netbsd openbsd - - package socket - diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/patches/series golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/patches/series --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/patches/series 2018-07-09 02:33:49.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -01-Fix_s390x_build.patch diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/rules golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/rules --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/rules 2018-07-09 02:33:49.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/rules 2019-08-17 12:00:23.000000000 +0000 @@ -5,9 +5,6 @@ # Exclude building the unused h2i binary to avoid circular dependency # with golang-golang-x-crypto-dev. export DH_GOLANG_EXCLUDES := golang.org/x/net/http2/h2i -# Include test fixtures. -export DH_GOLANG_INSTALL_EXTRA := html/charset/testdata html/testdata \ - bpf/testdata %: dh $@ --buildsystem=golang --with=golang --builddirectory=build diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/source/lintian-overrides golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/source/lintian-overrides --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/source/lintian-overrides 2018-07-09 02:33:49.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/source/lintian-overrides 2019-08-17 12:00:23.000000000 +0000 @@ -1,3 +1,2 @@ -golang-golang-x-net-dev source: debian-watch-file-is-missing # This is just a mention of the old repository in the description. golang-golang-x-net-dev source: obsolete-url-in-packaging debian/control https://code.google.com/p/go.net/ diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/watch golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/watch --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/debian/watch 1970-01-01 00:00:00.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/debian/watch 2019-08-17 12:00:23.000000000 +0000 @@ -0,0 +1,4 @@ +version=4 +opts="mode=git, pgpmode=none, pretty=0.0+git%cd.%h, dversionmangle=s/\+dfsg\d*$//,repacksuffix=+dfsg" \ +https://github.com/golang/net.git \ +HEAD debian diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/dns/dnsmessage/example_test.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/dns/dnsmessage/example_test.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/dns/dnsmessage/example_test.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/dns/dnsmessage/example_test.go 2019-08-17 11:56:26.000000000 +0000 @@ -37,20 +37,20 @@ }, Answers: []dnsmessage.Resource{ { - dnsmessage.ResourceHeader{ + Header: dnsmessage.ResourceHeader{ Name: mustNewName("foo.bar.example.com."), Type: dnsmessage.TypeA, Class: dnsmessage.ClassINET, }, - &dnsmessage.AResource{[4]byte{127, 0, 0, 1}}, + Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 1}}, }, { - dnsmessage.ResourceHeader{ + Header: dnsmessage.ResourceHeader{ Name: mustNewName("bar.example.com."), Type: dnsmessage.TypeA, Class: dnsmessage.ClassINET, }, - &dnsmessage.AResource{[4]byte{127, 0, 0, 2}}, + Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 2}}, }, }, } diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/dns/dnsmessage/message.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/dns/dnsmessage/message.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/dns/dnsmessage/message.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/dns/dnsmessage/message.go 2019-08-17 11:56:26.000000000 +0000 @@ -5,6 +5,9 @@ // Package dnsmessage provides a mostly RFC 1035 compliant implementation of // DNS message packing and unpacking. // +// The package also supports messages with Extension Mechanisms for DNS +// (EDNS(0)) as defined in RFC 6891. +// // This implementation is designed to minimize heap allocations and avoid // unnecessary packing and unpacking as much as possible. package dnsmessage @@ -18,16 +21,6 @@ // A Type is a type of DNS request and response. type Type uint16 -// A Class is a type of network. -type Class uint16 - -// An OpCode is a DNS operation code. -type OpCode uint16 - -// An RCode is a DNS response status code. -type RCode uint16 - -// Wire constants. const ( // ResourceHeader.Type and Question.Type TypeA Type = 1 @@ -39,6 +32,7 @@ TypeTXT Type = 16 TypeAAAA Type = 28 TypeSRV Type = 33 + TypeOPT Type = 41 // Question.Type TypeWKS Type = 11 @@ -46,7 +40,46 @@ TypeMINFO Type = 14 TypeAXFR Type = 252 TypeALL Type = 255 +) + +var typeNames = map[Type]string{ + TypeA: "TypeA", + TypeNS: "TypeNS", + TypeCNAME: "TypeCNAME", + TypeSOA: "TypeSOA", + TypePTR: "TypePTR", + TypeMX: "TypeMX", + TypeTXT: "TypeTXT", + TypeAAAA: "TypeAAAA", + TypeSRV: "TypeSRV", + TypeOPT: "TypeOPT", + TypeWKS: "TypeWKS", + TypeHINFO: "TypeHINFO", + TypeMINFO: "TypeMINFO", + TypeAXFR: "TypeAXFR", + TypeALL: "TypeALL", +} + +// String implements fmt.Stringer.String. +func (t Type) String() string { + if n, ok := typeNames[t]; ok { + return n + } + return printUint16(uint16(t)) +} + +// GoString implements fmt.GoStringer.GoString. +func (t Type) GoString() string { + if n, ok := typeNames[t]; ok { + return "dnsmessage." + n + } + return printUint16(uint16(t)) +} +// A Class is a type of network. +type Class uint16 + +const ( // ResourceHeader.Class and Question.Class ClassINET Class = 1 ClassCSNET Class = 2 @@ -55,7 +88,44 @@ // Question.Class ClassANY Class = 255 +) + +var classNames = map[Class]string{ + ClassINET: "ClassINET", + ClassCSNET: "ClassCSNET", + ClassCHAOS: "ClassCHAOS", + ClassHESIOD: "ClassHESIOD", + ClassANY: "ClassANY", +} + +// String implements fmt.Stringer.String. +func (c Class) String() string { + if n, ok := classNames[c]; ok { + return n + } + return printUint16(uint16(c)) +} + +// GoString implements fmt.GoStringer.GoString. +func (c Class) GoString() string { + if n, ok := classNames[c]; ok { + return "dnsmessage." + n + } + return printUint16(uint16(c)) +} +// An OpCode is a DNS operation code. +type OpCode uint16 + +// GoString implements fmt.GoStringer.GoString. +func (o OpCode) GoString() string { + return printUint16(uint16(o)) +} + +// An RCode is a DNS response status code. +type RCode uint16 + +const ( // Message.Rcode RCodeSuccess RCode = 0 RCodeFormatError RCode = 1 @@ -65,6 +135,116 @@ RCodeRefused RCode = 5 ) +var rCodeNames = map[RCode]string{ + RCodeSuccess: "RCodeSuccess", + RCodeFormatError: "RCodeFormatError", + RCodeServerFailure: "RCodeServerFailure", + RCodeNameError: "RCodeNameError", + RCodeNotImplemented: "RCodeNotImplemented", + RCodeRefused: "RCodeRefused", +} + +// String implements fmt.Stringer.String. +func (r RCode) String() string { + if n, ok := rCodeNames[r]; ok { + return n + } + return printUint16(uint16(r)) +} + +// GoString implements fmt.GoStringer.GoString. +func (r RCode) GoString() string { + if n, ok := rCodeNames[r]; ok { + return "dnsmessage." + n + } + return printUint16(uint16(r)) +} + +func printPaddedUint8(i uint8) string { + b := byte(i) + return string([]byte{ + b/100 + '0', + b/10%10 + '0', + b%10 + '0', + }) +} + +func printUint8Bytes(buf []byte, i uint8) []byte { + b := byte(i) + if i >= 100 { + buf = append(buf, b/100+'0') + } + if i >= 10 { + buf = append(buf, b/10%10+'0') + } + return append(buf, b%10+'0') +} + +func printByteSlice(b []byte) string { + if len(b) == 0 { + return "" + } + buf := make([]byte, 0, 5*len(b)) + buf = printUint8Bytes(buf, uint8(b[0])) + for _, n := range b[1:] { + buf = append(buf, ',', ' ') + buf = printUint8Bytes(buf, uint8(n)) + } + return string(buf) +} + +const hexDigits = "0123456789abcdef" + +func printString(str []byte) string { + buf := make([]byte, 0, len(str)) + for i := 0; i < len(str); i++ { + c := str[i] + if c == '.' || c == '-' || c == ' ' || + 'A' <= c && c <= 'Z' || + 'a' <= c && c <= 'z' || + '0' <= c && c <= '9' { + buf = append(buf, c) + continue + } + + upper := c >> 4 + lower := (c << 4) >> 4 + buf = append( + buf, + '\\', + 'x', + hexDigits[upper], + hexDigits[lower], + ) + } + return string(buf) +} + +func printUint16(i uint16) string { + return printUint32(uint32(i)) +} + +func printUint32(i uint32) string { + // Max value is 4294967295. + buf := make([]byte, 10) + for b, d := buf, uint32(1000000000); d > 0; d /= 10 { + b[0] = byte(i/d%10 + '0') + if b[0] == '0' && len(b) == len(buf) && len(buf) > 1 { + buf = buf[1:] + } + b = b[1:] + i %= d + } + return string(buf) +} + +func printBool(b bool) string { + if b { + return "true" + } + return "false" +} + var ( // ErrNotStarted indicates that the prerequisite information isn't // available yet because the previous records haven't been appropriately @@ -90,6 +270,8 @@ errTooManyAuthorities = errors.New("too many Authorities to pack (>65535)") errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)") errNonCanonicalName = errors.New("name is not in canonical format (it must end with a .)") + errStringTooLong = errors.New("character string exceeds maximum length (255)") + errCompressedSRV = errors.New("compressed name in SRV resource data") ) // Internal constants. @@ -159,6 +341,19 @@ return } +// GoString implements fmt.GoStringer.GoString. +func (m *Header) GoString() string { + return "dnsmessage.Header{" + + "ID: " + printUint16(m.ID) + ", " + + "Response: " + printBool(m.Response) + ", " + + "OpCode: " + m.OpCode.GoString() + ", " + + "Authoritative: " + printBool(m.Authoritative) + ", " + + "Truncated: " + printBool(m.Truncated) + ", " + + "RecursionDesired: " + printBool(m.RecursionDesired) + ", " + + "RecursionAvailable: " + printBool(m.RecursionAvailable) + ", " + + "RCode: " + m.RCode.GoString() + "}" +} + // Message is a representation of a DNS message. type Message struct { Header @@ -218,6 +413,7 @@ return 0 } +// pack appends the wire format of the header to msg. func (h *header) pack(msg []byte) []byte { msg = packUint16(msg, h.id) msg = packUint16(msg, h.bits) @@ -270,32 +466,43 @@ Body ResourceBody } +func (r *Resource) GoString() string { + return "dnsmessage.Resource{" + + "Header: " + r.Header.GoString() + + ", Body: &" + r.Body.GoString() + + "}" +} + // A ResourceBody is a DNS resource record minus the header. type ResourceBody interface { // pack packs a Resource except for its header. - pack(msg []byte, compression map[string]int) ([]byte, error) + pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) // realType returns the actual type of the Resource. This is used to // fill in the header Type field. realType() Type + + // GoString implements fmt.GoStringer.GoString. + GoString() string } -func (r *Resource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// pack appends the wire format of the Resource to msg. +func (r *Resource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { if r.Body == nil { return msg, errNilResouceBody } oldMsg := msg r.Header.Type = r.Body.realType() - msg, length, err := r.Header.pack(msg, compression) + msg, lenOff, err := r.Header.pack(msg, compression, compressionOff) if err != nil { return msg, &nestedError{"ResourceHeader", err} } preLen := len(msg) - msg, err = r.Body.pack(msg, compression) + msg, err = r.Body.pack(msg, compression, compressionOff) if err != nil { return msg, &nestedError{"content", err} } - if err := r.Header.fixLen(msg, length, preLen); err != nil { + if err := r.Header.fixLen(msg, lenOff, preLen); err != nil { return oldMsg, err } return msg, nil @@ -436,7 +643,13 @@ // AllQuestions parses all Questions. func (p *Parser) AllQuestions() ([]Question, error) { - qs := make([]Question, 0, p.header.questions) + // Multiple questions are valid according to the spec, + // but servers don't actually support them. There will + // be at most one question here. + // + // Do not pre-allocate based on info in p.header, since + // the data is untrusted. + qs := []Question{} for { q, err := p.Question() if err == ErrSectionDone { @@ -492,7 +705,16 @@ // AllAnswers parses all Answer Resources. func (p *Parser) AllAnswers() ([]Resource, error) { - as := make([]Resource, 0, p.header.answers) + // The most common query is for A/AAAA, which usually returns + // a handful of IPs. + // + // Pre-allocate up to a certain limit, since p.header is + // untrusted data. + n := int(p.header.answers) + if n > 20 { + n = 20 + } + as := make([]Resource, 0, n) for { a, err := p.Answer() if err == ErrSectionDone { @@ -533,7 +755,16 @@ // AllAuthorities parses all Authority Resources. func (p *Parser) AllAuthorities() ([]Resource, error) { - as := make([]Resource, 0, p.header.authorities) + // Authorities contains SOA in case of NXDOMAIN and friends, + // otherwise it is empty. + // + // Pre-allocate up to a certain limit, since p.header is + // untrusted data. + n := int(p.header.authorities) + if n > 10 { + n = 10 + } + as := make([]Resource, 0, n) for { a, err := p.Authority() if err == ErrSectionDone { @@ -574,7 +805,16 @@ // AllAdditionals parses all Additional Resources. func (p *Parser) AllAdditionals() ([]Resource, error) { - as := make([]Resource, 0, p.header.additionals) + // Additionals usually contain OPT, and sometimes A/AAAA + // glue records. + // + // Pre-allocate up to a certain limit, since p.header is + // untrusted data. + n := int(p.header.additionals) + if n > 10 { + n = 10 + } + as := make([]Resource, 0, n) for { a, err := p.Additional() if err == ErrSectionDone { @@ -765,6 +1005,24 @@ return r, nil } +// OPTResource parses a single OPTResource. +// +// One of the XXXHeader methods must have been called before calling this +// method. +func (p *Parser) OPTResource() (OPTResource, error) { + if !p.resHeaderValid || p.resHeader.Type != TypeOPT { + return OPTResource{}, ErrNotStarted + } + r, err := unpackOPTResource(p.msg, p.off, p.resHeader.Length) + if err != nil { + return OPTResource{}, err + } + p.off += int(p.resHeader.Length) + p.resHeaderValid = false + p.index++ + return r, nil +} + // Unpack parses a full Message. func (m *Message) Unpack(msg []byte) error { var p Parser @@ -819,6 +1077,7 @@ h.authorities = uint16(len(m.Authorities)) h.additionals = uint16(len(m.Additionals)) + compressionOff := len(b) msg := h.pack(b) // RFC 1035 allows (but does not require) compression for packing. RFC @@ -833,25 +1092,25 @@ for i := range m.Questions { var err error - if msg, err = m.Questions[i].pack(msg, compression); err != nil { + if msg, err = m.Questions[i].pack(msg, compression, compressionOff); err != nil { return nil, &nestedError{"packing Question", err} } } for i := range m.Answers { var err error - if msg, err = m.Answers[i].pack(msg, compression); err != nil { + if msg, err = m.Answers[i].pack(msg, compression, compressionOff); err != nil { return nil, &nestedError{"packing Answer", err} } } for i := range m.Authorities { var err error - if msg, err = m.Authorities[i].pack(msg, compression); err != nil { + if msg, err = m.Authorities[i].pack(msg, compression, compressionOff); err != nil { return nil, &nestedError{"packing Authority", err} } } for i := range m.Additionals { var err error - if msg, err = m.Additionals[i].pack(msg, compression); err != nil { + if msg, err = m.Additionals[i].pack(msg, compression, compressionOff); err != nil { return nil, &nestedError{"packing Additional", err} } } @@ -859,37 +1118,104 @@ return msg, nil } +// GoString implements fmt.GoStringer.GoString. +func (m *Message) GoString() string { + s := "dnsmessage.Message{Header: " + m.Header.GoString() + ", " + + "Questions: []dnsmessage.Question{" + if len(m.Questions) > 0 { + s += m.Questions[0].GoString() + for _, q := range m.Questions[1:] { + s += ", " + q.GoString() + } + } + s += "}, Answers: []dnsmessage.Resource{" + if len(m.Answers) > 0 { + s += m.Answers[0].GoString() + for _, a := range m.Answers[1:] { + s += ", " + a.GoString() + } + } + s += "}, Authorities: []dnsmessage.Resource{" + if len(m.Authorities) > 0 { + s += m.Authorities[0].GoString() + for _, a := range m.Authorities[1:] { + s += ", " + a.GoString() + } + } + s += "}, Additionals: []dnsmessage.Resource{" + if len(m.Additionals) > 0 { + s += m.Additionals[0].GoString() + for _, a := range m.Additionals[1:] { + s += ", " + a.GoString() + } + } + return s + "}}" +} + // A Builder allows incrementally packing a DNS message. +// +// Example usage: +// buf := make([]byte, 2, 514) +// b := NewBuilder(buf, Header{...}) +// b.EnableCompression() +// // Optionally start a section and add things to that section. +// // Repeat adding sections as necessary. +// buf, err := b.Finish() +// // If err is nil, buf[2:] will contain the built bytes. type Builder struct { - msg []byte - header header - section section + // msg is the storage for the message being built. + msg []byte + + // section keeps track of the current section being built. + section section + + // header keeps track of what should go in the header when Finish is + // called. + header header + + // start is the starting index of the bytes allocated in msg for header. + start int + + // compression is a mapping from name suffixes to their starting index + // in msg. compression map[string]int } -// Start initializes the builder. +// NewBuilder creates a new builder with compression disabled. // -// buf is optional (nil is fine), but if provided, Start takes ownership of buf. -func (b *Builder) Start(buf []byte, h Header) { - b.StartWithoutCompression(buf, h) - b.compression = map[string]int{} -} - -// StartWithoutCompression initializes the builder with compression disabled. +// Note: Most users will want to immediately enable compression with the +// EnableCompression method. See that method's comment for why you may or may +// not want to enable compression. // -// This avoids compression related allocations, but can result in larger message -// sizes. Be careful with this mode as it can cause messages to exceed the UDP -// size limit. -// -// buf is optional (nil is fine), but if provided, Start takes ownership of buf. -func (b *Builder) StartWithoutCompression(buf []byte, h Header) { - *b = Builder{msg: buf} - b.header.id, b.header.bits = h.pack() - if cap(b.msg) < headerLen { - b.msg = make([]byte, 0, packStartingCap) +// The DNS message is appended to the provided initial buffer buf (which may be +// nil) as it is built. The final message is returned by the (*Builder).Finish +// method, which may return the same underlying array if there was sufficient +// capacity in the slice. +func NewBuilder(buf []byte, h Header) Builder { + if buf == nil { + buf = make([]byte, 0, packStartingCap) } - b.msg = b.msg[:headerLen] + b := Builder{msg: buf, start: len(buf)} + b.header.id, b.header.bits = h.pack() + var hb [headerLen]byte + b.msg = append(b.msg, hb[:]...) b.section = sectionHeader + return b +} + +// EnableCompression enables compression in the Builder. +// +// Leaving compression disabled avoids compression related allocations, but can +// result in larger message sizes. Be careful with this mode as it can cause +// messages to exceed the UDP size limit. +// +// According to RFC 1035, section 4.1.4, the use of compression is optional, but +// all implementations must accept both compressed and uncompressed DNS +// messages. +// +// Compression should be enabled before any sections are added for best results. +func (b *Builder) EnableCompression() { + b.compression = map[string]int{} } func (b *Builder) startCheck(s section) error { @@ -970,7 +1296,7 @@ if b.section > sectionQuestions { return ErrSectionDone } - msg, err := q.pack(b.msg, b.compression) + msg, err := q.pack(b.msg, b.compression, b.start) if err != nil { return err } @@ -997,15 +1323,15 @@ return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"CNAMEResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1021,15 +1347,15 @@ return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"MXResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1045,15 +1371,15 @@ return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"NSResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1069,15 +1395,15 @@ return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"PTRResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1093,15 +1419,15 @@ return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"SOAResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1117,15 +1443,15 @@ return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"TXTResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1141,15 +1467,15 @@ return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"SRVResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1165,15 +1491,15 @@ return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"AResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1189,15 +1515,39 @@ return err } h.Type = r.realType() - msg, length, err := h.pack(b.msg, b.compression) + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) if err != nil { return &nestedError{"ResourceHeader", err} } preLen := len(msg) - if msg, err = r.pack(msg, b.compression); err != nil { + if msg, err = r.pack(msg, b.compression, b.start); err != nil { return &nestedError{"AAAAResource body", err} } - if err := h.fixLen(msg, length, preLen); err != nil { + if err := h.fixLen(msg, lenOff, preLen); err != nil { + return err + } + if err := b.incrementSectionCount(); err != nil { + return err + } + b.msg = msg + return nil +} + +// OPTResource adds a single OPTResource. +func (b *Builder) OPTResource(h ResourceHeader, r OPTResource) error { + if err := b.checkResourceSection(); err != nil { + return err + } + h.Type = r.realType() + msg, lenOff, err := h.pack(b.msg, b.compression, b.start) + if err != nil { + return &nestedError{"ResourceHeader", err} + } + preLen := len(msg) + if msg, err = r.pack(msg, b.compression, b.start); err != nil { + return &nestedError{"OPTResource body", err} + } + if err := h.fixLen(msg, lenOff, preLen); err != nil { return err } if err := b.incrementSectionCount(); err != nil { @@ -1213,7 +1563,8 @@ return nil, ErrNotStarted } b.section = sectionDone - b.header.pack(b.msg[:0]) + // Space for the header was allocated in NewBuilder. + b.header.pack(b.msg[b.start:b.start]) return b.msg, nil } @@ -1243,20 +1594,30 @@ Length uint16 } -// pack packs all of the fields in a ResourceHeader except for the length. The -// length bytes are returned as a slice so they can be filled in after the rest -// of the Resource has been packed. -func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int) (msg []byte, length []byte, err error) { +// GoString implements fmt.GoStringer.GoString. +func (h *ResourceHeader) GoString() string { + return "dnsmessage.ResourceHeader{" + + "Name: " + h.Name.GoString() + ", " + + "Type: " + h.Type.GoString() + ", " + + "Class: " + h.Class.GoString() + ", " + + "TTL: " + printUint32(h.TTL) + ", " + + "Length: " + printUint16(h.Length) + "}" +} + +// pack appends the wire format of the ResourceHeader to oldMsg. +// +// lenOff is the offset in msg where the Length field was packed. +func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int, compressionOff int) (msg []byte, lenOff int, err error) { msg = oldMsg - if msg, err = h.Name.pack(msg, compression); err != nil { - return oldMsg, nil, &nestedError{"Name", err} + if msg, err = h.Name.pack(msg, compression, compressionOff); err != nil { + return oldMsg, 0, &nestedError{"Name", err} } msg = packType(msg, h.Type) msg = packClass(msg, h.Class) msg = packUint32(msg, h.TTL) - lenBegin := len(msg) + lenOff = len(msg) msg = packUint16(msg, h.Length) - return msg, msg[lenBegin : lenBegin+uint16Len], nil + return msg, lenOff, nil } func (h *ResourceHeader) unpack(msg []byte, off int) (int, error) { @@ -1280,19 +1641,63 @@ return newOff, nil } -func (h *ResourceHeader) fixLen(msg []byte, length []byte, preLen int) error { +// fixLen updates a packed ResourceHeader to include the length of the +// ResourceBody. +// +// lenOff is the offset of the ResourceHeader.Length field in msg. +// +// preLen is the length that msg was before the ResourceBody was packed. +func (h *ResourceHeader) fixLen(msg []byte, lenOff int, preLen int) error { conLen := len(msg) - preLen if conLen > int(^uint16(0)) { return errResTooLong } // Fill in the length now that we know how long the content is. - packUint16(length[:0], uint16(conLen)) + packUint16(msg[lenOff:lenOff], uint16(conLen)) h.Length = uint16(conLen) return nil } +// EDNS(0) wire costants. +const ( + edns0Version = 0 + + edns0DNSSECOK = 0x00008000 + ednsVersionMask = 0x00ff0000 + edns0DNSSECOKMask = 0x00ff8000 +) + +// SetEDNS0 configures h for EDNS(0). +// +// The provided extRCode must be an extedned RCode. +func (h *ResourceHeader) SetEDNS0(udpPayloadLen int, extRCode RCode, dnssecOK bool) error { + h.Name = Name{Data: [nameLen]byte{'.'}, Length: 1} // RFC 6891 section 6.1.2 + h.Type = TypeOPT + h.Class = Class(udpPayloadLen) + h.TTL = uint32(extRCode) >> 4 << 24 + if dnssecOK { + h.TTL |= edns0DNSSECOK + } + return nil +} + +// DNSSECAllowed reports whether the DNSSEC OK bit is set. +func (h *ResourceHeader) DNSSECAllowed() bool { + return h.TTL&edns0DNSSECOKMask == edns0DNSSECOK // RFC 6891 section 6.1.3 +} + +// ExtendedRCode returns an extended RCode. +// +// The provided rcode must be the RCode in DNS message header. +func (h *ResourceHeader) ExtendedRCode(rcode RCode) RCode { + if h.TTL&ednsVersionMask == edns0Version { // RFC 6891 section 6.1.3 + return RCode(h.TTL>>24<<4) | rcode + } + return rcode +} + func skipResource(msg []byte, off int) (int, error) { newOff, err := skipName(msg, off) if err != nil { @@ -1317,6 +1722,7 @@ return newOff, nil } +// packUint16 appends the wire format of field to msg. func packUint16(msg []byte, field uint16) []byte { return append(msg, byte(field>>8), byte(field)) } @@ -1335,6 +1741,7 @@ return off + uint16Len, nil } +// packType appends the wire format of field to msg. func packType(msg []byte, field Type) []byte { return packUint16(msg, uint16(field)) } @@ -1348,6 +1755,7 @@ return skipUint16(msg, off) } +// packClass appends the wire format of field to msg. func packClass(msg []byte, field Class) []byte { return packUint16(msg, uint16(field)) } @@ -1361,6 +1769,7 @@ return skipUint16(msg, off) } +// packUint32 appends the wire format of field to msg. func packUint32(msg []byte, field uint32) []byte { return append( msg, @@ -1386,17 +1795,16 @@ return off + uint32Len, nil } -func packText(msg []byte, field string) []byte { - for len(field) > 0 { - l := len(field) - if l > 255 { - l = 255 - } - msg = append(msg, byte(l)) - msg = append(msg, field[:l]...) - field = field[l:] +// packText appends the wire format of field to msg. +func packText(msg []byte, field string) ([]byte, error) { + l := len(field) + if l > 255 { + return nil, errStringTooLong } - return msg + msg = append(msg, byte(l)) + msg = append(msg, field...) + + return msg, nil } func unpackText(msg []byte, off int) (string, int, error) { @@ -1422,6 +1830,7 @@ return endOff, nil } +// packBytes appends the wire format of field to msg. func packBytes(msg []byte, field []byte) []byte { return append(msg, field...) } @@ -1462,18 +1871,33 @@ return n, nil } +// MustNewName creates a new Name from a string and panics on error. +func MustNewName(name string) Name { + n, err := NewName(name) + if err != nil { + panic("creating name: " + err.Error()) + } + return n +} + +// String implements fmt.Stringer.String. func (n Name) String() string { return string(n.Data[:n.Length]) } -// pack packs a domain name. +// GoString implements fmt.GoStringer.GoString. +func (n *Name) GoString() string { + return `dnsmessage.MustNewName("` + printString(n.Data[:n.Length]) + `")` +} + +// pack appends the wire format of the Name to msg. // // Domain names are a sequence of counted strings split at the dots. They end // with a zero-length string. Compression can be used to reuse domain suffixes. // // The compression map will be updated with new domain suffixes. If compression // is nil, compression will not be used. -func (n *Name) pack(msg []byte, compression map[string]int) ([]byte, error) { +func (n *Name) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { oldMsg := msg // Add a trailing dot to canonicalize name. @@ -1525,7 +1949,7 @@ // Miss. Add the suffix to the compression table if the // offset can be stored in the available 14 bytes. if len(msg) <= int(^uint16(0)>>2) { - compression[string(n.Data[i:])] = len(msg) + compression[string(n.Data[i:])] = len(msg) - compressionOff } } } @@ -1534,6 +1958,10 @@ // unpack unpacks a domain name. func (n *Name) unpack(msg []byte, off int) (int, error) { + return n.unpackCompressed(msg, off, true /* allowCompression */) +} + +func (n *Name) unpackCompressed(msg []byte, off int, allowCompression bool) (int, error) { // currOff is the current working offset. currOff := off @@ -1569,6 +1997,9 @@ name = append(name, '.') currOff = endOff case 0xC0: // Pointer + if !allowCompression { + return off, errCompressedSRV + } if currOff >= len(msg) { return off, errInvalidPtr } @@ -1648,8 +2079,9 @@ Class Class } -func (q *Question) pack(msg []byte, compression map[string]int) ([]byte, error) { - msg, err := q.Name.pack(msg, compression) +// pack appends the wire format of the Question to msg. +func (q *Question) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + msg, err := q.Name.pack(msg, compression, compressionOff) if err != nil { return msg, &nestedError{"Name", err} } @@ -1657,6 +2089,14 @@ return packClass(msg, q.Class), nil } +// GoString implements fmt.GoStringer.GoString. +func (q *Question) GoString() string { + return "dnsmessage.Question{" + + "Name: " + q.Name.GoString() + ", " + + "Type: " + q.Type.GoString() + ", " + + "Class: " + q.Class.GoString() + "}" +} + func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, int, error) { var ( r ResourceBody @@ -1709,6 +2149,11 @@ rb, err = unpackSRVResource(msg, off) r = &rb name = "SRV" + case TypeOPT: + var rb OPTResource + rb, err = unpackOPTResource(msg, off, hdr.Length) + r = &rb + name = "OPT" } if err != nil { return nil, off, &nestedError{name + " record", err} @@ -1728,8 +2173,14 @@ return TypeCNAME } -func (r *CNAMEResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return r.CNAME.pack(msg, compression) +// pack appends the wire format of the CNAMEResource to msg. +func (r *CNAMEResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + return r.CNAME.pack(msg, compression, compressionOff) +} + +// GoString implements fmt.GoStringer.GoString. +func (r *CNAMEResource) GoString() string { + return "dnsmessage.CNAMEResource{CNAME: " + r.CNAME.GoString() + "}" } func unpackCNAMEResource(msg []byte, off int) (CNAMEResource, error) { @@ -1750,16 +2201,24 @@ return TypeMX } -func (r *MXResource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// pack appends the wire format of the MXResource to msg. +func (r *MXResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { oldMsg := msg msg = packUint16(msg, r.Pref) - msg, err := r.MX.pack(msg, compression) + msg, err := r.MX.pack(msg, compression, compressionOff) if err != nil { return oldMsg, &nestedError{"MXResource.MX", err} } return msg, nil } +// GoString implements fmt.GoStringer.GoString. +func (r *MXResource) GoString() string { + return "dnsmessage.MXResource{" + + "Pref: " + printUint16(r.Pref) + ", " + + "MX: " + r.MX.GoString() + "}" +} + func unpackMXResource(msg []byte, off int) (MXResource, error) { pref, off, err := unpackUint16(msg, off) if err != nil { @@ -1781,8 +2240,14 @@ return TypeNS } -func (r *NSResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return r.NS.pack(msg, compression) +// pack appends the wire format of the NSResource to msg. +func (r *NSResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + return r.NS.pack(msg, compression, compressionOff) +} + +// GoString implements fmt.GoStringer.GoString. +func (r *NSResource) GoString() string { + return "dnsmessage.NSResource{NS: " + r.NS.GoString() + "}" } func unpackNSResource(msg []byte, off int) (NSResource, error) { @@ -1802,8 +2267,14 @@ return TypePTR } -func (r *PTRResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return r.PTR.pack(msg, compression) +// pack appends the wire format of the PTRResource to msg. +func (r *PTRResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + return r.PTR.pack(msg, compression, compressionOff) +} + +// GoString implements fmt.GoStringer.GoString. +func (r *PTRResource) GoString() string { + return "dnsmessage.PTRResource{PTR: " + r.PTR.GoString() + "}" } func unpackPTRResource(msg []byte, off int) (PTRResource, error) { @@ -1833,13 +2304,14 @@ return TypeSOA } -func (r *SOAResource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// pack appends the wire format of the SOAResource to msg. +func (r *SOAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { oldMsg := msg - msg, err := r.NS.pack(msg, compression) + msg, err := r.NS.pack(msg, compression, compressionOff) if err != nil { return oldMsg, &nestedError{"SOAResource.NS", err} } - msg, err = r.MBox.pack(msg, compression) + msg, err = r.MBox.pack(msg, compression, compressionOff) if err != nil { return oldMsg, &nestedError{"SOAResource.MBox", err} } @@ -1850,6 +2322,18 @@ return packUint32(msg, r.MinTTL), nil } +// GoString implements fmt.GoStringer.GoString. +func (r *SOAResource) GoString() string { + return "dnsmessage.SOAResource{" + + "NS: " + r.NS.GoString() + ", " + + "MBox: " + r.MBox.GoString() + ", " + + "Serial: " + printUint32(r.Serial) + ", " + + "Refresh: " + printUint32(r.Refresh) + ", " + + "Retry: " + printUint32(r.Retry) + ", " + + "Expire: " + printUint32(r.Expire) + ", " + + "MinTTL: " + printUint32(r.MinTTL) + "}" +} + func unpackSOAResource(msg []byte, off int) (SOAResource, error) { var ns Name off, err := ns.unpack(msg, off) @@ -1885,19 +2369,41 @@ // A TXTResource is a TXT Resource record. type TXTResource struct { - Txt string // Not a domain name. + TXT []string } func (r *TXTResource) realType() Type { return TypeTXT } -func (r *TXTResource) pack(msg []byte, compression map[string]int) ([]byte, error) { - return packText(msg, r.Txt), nil +// pack appends the wire format of the TXTResource to msg. +func (r *TXTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + oldMsg := msg + for _, s := range r.TXT { + var err error + msg, err = packText(msg, s) + if err != nil { + return oldMsg, err + } + } + return msg, nil +} + +// GoString implements fmt.GoStringer.GoString. +func (r *TXTResource) GoString() string { + s := "dnsmessage.TXTResource{TXT: []string{" + if len(r.TXT) == 0 { + return s + "}}" + } + s += `"` + printString([]byte(r.TXT[0])) + for _, t := range r.TXT[1:] { + s += `", "` + printString([]byte(t)) + } + return s + `"}}` } func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) { - var txt string + txts := make([]string, 0, 1) for n := uint16(0); n < length; { var t string var err error @@ -1909,9 +2415,9 @@ return TXTResource{}, errCalcLen } n += uint16(len(t)) + 1 - txt += t + txts = append(txts, t) } - return TXTResource{txt}, nil + return TXTResource{txts}, nil } // An SRVResource is an SRV Resource record. @@ -1926,18 +2432,28 @@ return TypeSRV } -func (r *SRVResource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// pack appends the wire format of the SRVResource to msg. +func (r *SRVResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { oldMsg := msg msg = packUint16(msg, r.Priority) msg = packUint16(msg, r.Weight) msg = packUint16(msg, r.Port) - msg, err := r.Target.pack(msg, nil) + msg, err := r.Target.pack(msg, nil, compressionOff) if err != nil { return oldMsg, &nestedError{"SRVResource.Target", err} } return msg, nil } +// GoString implements fmt.GoStringer.GoString. +func (r *SRVResource) GoString() string { + return "dnsmessage.SRVResource{" + + "Priority: " + printUint16(r.Priority) + ", " + + "Weight: " + printUint16(r.Weight) + ", " + + "Port: " + printUint16(r.Port) + ", " + + "Target: " + r.Target.GoString() + "}" +} + func unpackSRVResource(msg []byte, off int) (SRVResource, error) { priority, off, err := unpackUint16(msg, off) if err != nil { @@ -1952,7 +2468,7 @@ return SRVResource{}, &nestedError{"Port", err} } var target Name - if _, err := target.unpack(msg, off); err != nil { + if _, err := target.unpackCompressed(msg, off, false /* allowCompression */); err != nil { return SRVResource{}, &nestedError{"Target", err} } return SRVResource{priority, weight, port, target}, nil @@ -1967,10 +2483,17 @@ return TypeA } -func (r *AResource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// pack appends the wire format of the AResource to msg. +func (r *AResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { return packBytes(msg, r.A[:]), nil } +// GoString implements fmt.GoStringer.GoString. +func (r *AResource) GoString() string { + return "dnsmessage.AResource{" + + "A: [4]byte{" + printByteSlice(r.A[:]) + "}}" +} + func unpackAResource(msg []byte, off int) (AResource, error) { var a [4]byte if _, err := unpackBytes(msg, off, a[:]); err != nil { @@ -1988,7 +2511,14 @@ return TypeAAAA } -func (r *AAAAResource) pack(msg []byte, compression map[string]int) ([]byte, error) { +// GoString implements fmt.GoStringer.GoString. +func (r *AAAAResource) GoString() string { + return "dnsmessage.AAAAResource{" + + "AAAA: [16]byte{" + printByteSlice(r.AAAA[:]) + "}}" +} + +// pack appends the wire format of the AAAAResource to msg. +func (r *AAAAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { return packBytes(msg, r.AAAA[:]), nil } @@ -1999,3 +2529,78 @@ } return AAAAResource{aaaa}, nil } + +// An OPTResource is an OPT pseudo Resource record. +// +// The pseudo resource record is part of the extension mechanisms for DNS +// as defined in RFC 6891. +type OPTResource struct { + Options []Option +} + +// An Option represents a DNS message option within OPTResource. +// +// The message option is part of the extension mechanisms for DNS as +// defined in RFC 6891. +type Option struct { + Code uint16 // option code + Data []byte +} + +// GoString implements fmt.GoStringer.GoString. +func (o *Option) GoString() string { + return "dnsmessage.Option{" + + "Code: " + printUint16(o.Code) + ", " + + "Data: []byte{" + printByteSlice(o.Data) + "}}" +} + +func (r *OPTResource) realType() Type { + return TypeOPT +} + +func (r *OPTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) { + for _, opt := range r.Options { + msg = packUint16(msg, opt.Code) + l := uint16(len(opt.Data)) + msg = packUint16(msg, l) + msg = packBytes(msg, opt.Data) + } + return msg, nil +} + +// GoString implements fmt.GoStringer.GoString. +func (r *OPTResource) GoString() string { + s := "dnsmessage.OPTResource{Options: []dnsmessage.Option{" + if len(r.Options) == 0 { + return s + "}}" + } + s += r.Options[0].GoString() + for _, o := range r.Options[1:] { + s += ", " + o.GoString() + } + return s + "}}" +} + +func unpackOPTResource(msg []byte, off int, length uint16) (OPTResource, error) { + var opts []Option + for oldOff := off; off < oldOff+int(length); { + var err error + var o Option + o.Code, off, err = unpackUint16(msg, off) + if err != nil { + return OPTResource{}, &nestedError{"Code", err} + } + var l uint16 + l, off, err = unpackUint16(msg, off) + if err != nil { + return OPTResource{}, &nestedError{"Data", err} + } + o.Data = make([]byte, l) + if copy(o.Data, msg[off:]) != int(l) { + return OPTResource{}, &nestedError{"Data", errCalcLen} + } + off += int(l) + opts = append(opts, o) + } + return OPTResource{opts}, nil +} diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/dns/dnsmessage/message_test.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/dns/dnsmessage/message_test.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/dns/dnsmessage/message_test.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/dns/dnsmessage/message_test.go 2019-08-17 11:56:26.000000000 +0000 @@ -8,15 +8,109 @@ "bytes" "fmt" "reflect" + "strings" "testing" ) -func mustNewName(name string) Name { - n, err := NewName(name) - if err != nil { +func TestPrintPaddedUint8(t *testing.T) { + tests := []struct { + num uint8 + want string + }{ + {0, "000"}, + {1, "001"}, + {9, "009"}, + {10, "010"}, + {99, "099"}, + {100, "100"}, + {124, "124"}, + {104, "104"}, + {120, "120"}, + {255, "255"}, + } + + for _, test := range tests { + if got := printPaddedUint8(test.num); got != test.want { + t.Errorf("got printPaddedUint8(%d) = %s, want = %s", test.num, got, test.want) + } + } +} + +func TestPrintUint8Bytes(t *testing.T) { + tests := []uint8{ + 0, + 1, + 9, + 10, + 99, + 100, + 124, + 104, + 120, + 255, + } + + for _, test := range tests { + if got, want := string(printUint8Bytes(nil, test)), fmt.Sprint(test); got != want { + t.Errorf("got printUint8Bytes(%d) = %s, want = %s", test, got, want) + } + } +} + +func TestPrintUint16(t *testing.T) { + tests := []uint16{ + 65535, + 0, + 1, + 10, + 100, + 1000, + 10000, + 324, + 304, + 320, + } + + for _, test := range tests { + if got, want := printUint16(test), fmt.Sprint(test); got != want { + t.Errorf("got printUint16(%d) = %s, want = %s", test, got, want) + } + } +} + +func TestPrintUint32(t *testing.T) { + tests := []uint32{ + 4294967295, + 65535, + 0, + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 324, + 304, + 320, + } + + for _, test := range tests { + if got, want := printUint32(test), fmt.Sprint(test); got != want { + t.Errorf("got printUint32(%d) = %s, want = %s", test, got, want) + } + } +} + +func mustEDNS0ResourceHeader(l int, extrc RCode, do bool) ResourceHeader { + h := ResourceHeader{Class: ClassINET} + if err := h.SetEDNS0(l, extrc, do); err != nil { panic(err) } - return n + return h } func (m *Message) String() string { @@ -50,7 +144,7 @@ func TestNameString(t *testing.T) { want := "foo" - name := mustNewName(want) + name := MustNewName(want) if got := fmt.Sprint(name); got != want { t.Errorf("got fmt.Sprint(%#v) = %s, want = %s", name, got, want) } @@ -58,13 +152,13 @@ func TestQuestionPackUnpack(t *testing.T) { want := Question{ - Name: mustNewName("."), + Name: MustNewName("."), Type: TypeA, Class: ClassINET, } - buf, err := want.pack(make([]byte, 1, 50), map[string]int{}) + buf, err := want.pack(make([]byte, 1, 50), map[string]int{}, 1) if err != nil { - t.Fatal("Packing failed:", err) + t.Fatal("Question.pack() =", err) } var p Parser p.msg = buf @@ -73,13 +167,13 @@ p.off = 1 got, err := p.Question() if err != nil { - t.Fatalf("Unpacking failed: %v\n%s", err, string(buf[1:])) + t.Fatalf("Parser{%q}.Question() = %v", string(buf[1:]), err) } if p.off != len(buf) { - t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", p.off, len(buf)) + t.Errorf("unpacked different amount than packed: got = %d, want = %d", p.off, len(buf)) } if !reflect.DeepEqual(got, want) { - t.Errorf("Got = %+v, want = %+v", got, want) + t.Errorf("got from Parser.Question() = %+v, want = %+v", got, want) } } @@ -99,11 +193,11 @@ for _, test := range tests { n, err := NewName(test) if err != nil { - t.Errorf("Creating name for %q: %v", test, err) + t.Errorf("NewName(%q) = %v", test, err) continue } if ns := n.String(); ns != test { - t.Errorf("Got %#v.String() = %q, want = %q", n, ns, test) + t.Errorf("got %#v.String() = %q, want = %q", n, ns, test) continue } } @@ -127,11 +221,11 @@ } for _, test := range tests { - in := mustNewName(test.in) - want := mustNewName(test.want) - buf, err := in.pack(make([]byte, 0, 30), map[string]int{}) + in := MustNewName(test.in) + want := MustNewName(test.want) + buf, err := in.pack(make([]byte, 0, 30), map[string]int{}, 0) if err != test.err { - t.Errorf("Packing of %q: got err = %v, want err = %v", test.in, err, test.err) + t.Errorf("got %q.pack() = %v, want = %v", test.in, err, test.err) continue } if test.err != nil { @@ -140,23 +234,45 @@ var got Name n, err := got.unpack(buf, 0) if err != nil { - t.Errorf("Unpacking for %q failed: %v", test.in, err) + t.Errorf("%q.unpack() = %v", test.in, err) continue } if n != len(buf) { t.Errorf( - "Unpacked different amount than packed for %q: got n = %d, want = %d", + "unpacked different amount than packed for %q: got = %d, want = %d", test.in, n, len(buf), ) } if got != want { - t.Errorf("Unpacking packing of %q: got = %#v, want = %#v", test.in, got, want) + t.Errorf("unpacking packing of %q: got = %#v, want = %#v", test.in, got, want) } } } +func TestIncompressibleName(t *testing.T) { + name := MustNewName("example.com.") + compression := map[string]int{} + buf, err := name.pack(make([]byte, 0, 100), compression, 0) + if err != nil { + t.Fatal("first Name.pack() =", err) + } + buf, err = name.pack(buf, compression, 0) + if err != nil { + t.Fatal("second Name.pack() =", err) + } + var n1 Name + off, err := n1.unpackCompressed(buf, 0, false /* allowCompression */) + if err != nil { + t.Fatal("unpacking incompressible name without pointers failed:", err) + } + var n2 Name + if _, err := n2.unpackCompressed(buf, off, false /* allowCompression */); err != errCompressedSRV { + t.Errorf("unpacking compressed incompressible name with pointers: got %v, want = %v", err, errCompressedSRV) + } +} + func checkErrorPrefix(err error, prefix string) bool { e, ok := err.(*nestedError) return ok && e.s == prefix @@ -176,7 +292,7 @@ for _, want := range wants { n, err := h.unpack(buf, 0) if n != 0 || !checkErrorPrefix(err, want) { - t.Errorf("got h.unpack([%d]byte, 0) = %d, %v, want = 0, %s", len(buf), n, err, want) + t.Errorf("got header.unpack([%d]byte, 0) = %d, %v, want = 0, %s", len(buf), n, err, want) } buf = append(buf, 0, 0) } @@ -188,7 +304,7 @@ for i := 0; i <= 1; i++ { _, err := p.Start([]byte{}) if !checkErrorPrefix(err, want) { - t.Errorf("got p.Start(nil) = _, %v, want = _, %s", err, want) + t.Errorf("got Parser.Start(nil) = _, %v, want = _, %s", err, want) } } } @@ -211,7 +327,7 @@ for _, test := range tests { if err := test.fn(&Parser{}); err != ErrNotStarted { - t.Errorf("got _, %v = p.%s(), want = _, %v", err, test.name, ErrNotStarted) + t.Errorf("got Parser.%s() = _ , %v, want = _, %v", test.name, err, ErrNotStarted) } } } @@ -221,7 +337,7 @@ { Questions: []Question{ { - Name: mustNewName("."), + Name: MustNewName("."), Type: TypeAAAA, Class: ClassINET, }, @@ -235,15 +351,49 @@ for i, want := range wants { b, err := want.Pack() if err != nil { - t.Fatalf("%d: packing failed: %v", i, err) + t.Fatalf("%d: Message.Pack() = %v", i, err) + } + var got Message + err = got.Unpack(b) + if err != nil { + t.Fatalf("%d: Message.Unapck() = %v", i, err) + } + if !reflect.DeepEqual(got, want) { + t.Errorf("%d: Message.Pack/Unpack() roundtrip: got = %+v, want = %+v", i, &got, &want) + } + } +} + +func TestDNSAppendPackUnpack(t *testing.T) { + wants := []Message{ + { + Questions: []Question{ + { + Name: MustNewName("."), + Type: TypeAAAA, + Class: ClassINET, + }, + }, + Answers: []Resource{}, + Authorities: []Resource{}, + Additionals: []Resource{}, + }, + largeTestMsg(), + } + for i, want := range wants { + b := make([]byte, 2, 514) + b, err := want.AppendPack(b) + if err != nil { + t.Fatalf("%d: Message.AppendPack() = %v", i, err) } + b = b[2:] var got Message err = got.Unpack(b) if err != nil { - t.Fatalf("%d: unpacking failed: %v", i, err) + t.Fatalf("%d: Message.Unapck() = %v", i, err) } if !reflect.DeepEqual(got, want) { - t.Errorf("%d: got = %+v, want = %+v", i, &got, &want) + t.Errorf("%d: Message.AppendPack/Unpack() roundtrip: got = %+v, want = %+v", i, &got, &want) } } } @@ -252,11 +402,11 @@ msg := largeTestMsg() buf, err := msg.Pack() if err != nil { - t.Fatal("Packing large test message:", err) + t.Fatal("Message.Pack() =", err) } var p Parser if _, err := p.Start(buf); err != nil { - t.Fatal(err) + t.Fatal("Parser.Start(non-nil) =", err) } tests := []struct { @@ -271,7 +421,7 @@ for _, test := range tests { for i := 1; i <= 3; i++ { if err := test.f(); err != nil { - t.Errorf("Call #%d to %s(): %v", i, test.name, err) + t.Errorf("%d: Parser.%s() = %v", i, test.name, err) } } } @@ -282,11 +432,11 @@ buf, err := msg.Pack() if err != nil { - t.Fatal("Packing test message:", err) + t.Fatal("Message.Pack() =", err) } var p Parser if _, err := p.Start(buf); err != nil { - t.Fatal(err) + t.Fatal("Parser.Start(non-nil) =", err) } tests := []struct { @@ -300,10 +450,10 @@ } for _, test := range tests { if err := test.f(); err != nil { - t.Errorf("First call: got %s() = %v, want = %v", test.name, err, nil) + t.Errorf("first Parser.%s() = %v, want = nil", test.name, err) } if err := test.f(); err != ErrSectionDone { - t.Errorf("Second call: got %s() = %v, want = %v", test.name, err, ErrSectionDone) + t.Errorf("second Parser.%s() = %v, want = %v", test.name, err, ErrSectionDone) } } } @@ -313,11 +463,11 @@ buf, err := msg.Pack() if err != nil { - t.Fatal("Packing test message:", err) + t.Fatal("Message.Pack() =", err) } var p Parser if _, err := p.Start(buf); err != nil { - t.Fatal(err) + t.Fatal("Parser.Srart(non-nil) =", err) } tests := []struct { @@ -332,10 +482,10 @@ } for _, test := range tests { if err := test.read(); err != nil { - t.Errorf("Got %s() = _, %v, want = _, %v", test.name, err, nil) + t.Errorf("got Parser.%s() = _, %v, want = _, nil", test.name, err) } if err := test.skip(); err != ErrSectionDone { - t.Errorf("Got Skip%s() = %v, want = %v", test.name, err, ErrSectionDone) + t.Errorf("got Parser.Skip%s() = %v, want = %v", test.name, err, ErrSectionDone) } } } @@ -354,7 +504,7 @@ } for _, test := range tests { if err := test.f(); err != ErrNotStarted { - t.Errorf("Got %s() = %v, want = %v", test.name, err, ErrNotStarted) + t.Errorf("got Parser.%s() = %v, want = %v", test.name, err, ErrNotStarted) } } } @@ -398,7 +548,7 @@ for _, test := range tests { if _, got := test.msg.Pack(); got != test.want { - t.Errorf("Packing %d %s: got = %v, want = %v", recs, test.name, got, test.want) + t.Errorf("got Message.Pack() for %d %s = %v, want = %v", recs, test.name, got, test.want) } } } @@ -406,31 +556,66 @@ func TestVeryLongTxt(t *testing.T) { want := Resource{ ResourceHeader{ - Name: mustNewName("foo.bar.example.com."), + Name: MustNewName("foo.bar.example.com."), Type: TypeTXT, Class: ClassINET, }, - &TXTResource{loremIpsum}, + &TXTResource{[]string{ + "", + "", + "foo bar", + "", + "www.example.com", + "www.example.com.", + strings.Repeat(".", 255), + }}, } - buf, err := want.pack(make([]byte, 0, 8000), map[string]int{}) + buf, err := want.pack(make([]byte, 0, 8000), map[string]int{}, 0) if err != nil { - t.Fatal("Packing failed:", err) + t.Fatal("Resource.pack() =", err) } var got Resource off, err := got.Header.unpack(buf, 0) if err != nil { - t.Fatal("Unpacking ResourceHeader failed:", err) + t.Fatal("ResourceHeader.unpack() =", err) } body, n, err := unpackResourceBody(buf, off, got.Header) if err != nil { - t.Fatal("Unpacking failed:", err) + t.Fatal("unpackResourceBody() =", err) } got.Body = body if n != len(buf) { - t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf)) + t.Errorf("unpacked different amount than packed: got = %d, want = %d", n, len(buf)) } if !reflect.DeepEqual(got, want) { - t.Errorf("Got = %#v, want = %#v", got, want) + t.Errorf("Resource.pack/unpack() roundtrip: got = %#v, want = %#v", got, want) + } +} + +func TestTooLongTxt(t *testing.T) { + rb := TXTResource{[]string{strings.Repeat(".", 256)}} + if _, err := rb.pack(make([]byte, 0, 8000), map[string]int{}, 0); err != errStringTooLong { + t.Errorf("packing TXTResource with 256 character string: got err = %v, want = %v", err, errStringTooLong) + } +} + +func TestStartAppends(t *testing.T) { + buf := make([]byte, 2, 514) + wantBuf := []byte{4, 44} + copy(buf, wantBuf) + + b := NewBuilder(buf, Header{}) + b.EnableCompression() + + buf, err := b.Finish() + if err != nil { + t.Fatal("Builder.Finish() =", err) + } + if got, want := len(buf), headerLen+2; got != want { + t.Errorf("got len(buf) = %d, want = %d", got, want) + } + if string(buf[:2]) != string(wantBuf) { + t.Errorf("original data not preserved, got = %#v, want = %#v", buf[:2], wantBuf) } } @@ -457,7 +642,7 @@ for _, env := range envs { for _, test := range tests { if got := test.fn(env.fn()); got != env.want { - t.Errorf("got Builder{%s}.Start%s = %v, want = %v", env.name, test.name, got, env.want) + t.Errorf("got Builder{%s}.Start%s() = %v, want = %v", env.name, test.name, got, env.want) } } } @@ -477,6 +662,7 @@ {"SRVResource", func(b *Builder) error { return b.SRVResource(ResourceHeader{}, SRVResource{}) }}, {"AResource", func(b *Builder) error { return b.AResource(ResourceHeader{}, AResource{}) }}, {"AAAAResource", func(b *Builder) error { return b.AAAAResource(ResourceHeader{}, AAAAResource{}) }}, + {"OPTResource", func(b *Builder) error { return b.OPTResource(ResourceHeader{}, OPTResource{}) }}, } envs := []struct { @@ -493,7 +679,7 @@ for _, env := range envs { for _, test := range tests { if got := test.fn(env.fn()); got != env.want { - t.Errorf("got Builder{%s}.%s = %v, want = %v", env.name, test.name, got, env.want) + t.Errorf("got Builder{%s}.%s() = %v, want = %v", env.name, test.name, got, env.want) } } } @@ -503,7 +689,7 @@ var b Builder want := ErrNotStarted if _, got := b.Finish(); got != want { - t.Errorf("got Builder{}.Finish() = %v, want = %v", got, want) + t.Errorf("got Builder.Finish() = %v, want = %v", got, want) } } @@ -511,89 +697,96 @@ msg := largeTestMsg() want, err := msg.Pack() if err != nil { - t.Fatal("Packing without builder:", err) + t.Fatal("Message.Pack() =", err) } - var b Builder - b.Start(nil, msg.Header) + b := NewBuilder(nil, msg.Header) + b.EnableCompression() if err := b.StartQuestions(); err != nil { - t.Fatal("b.StartQuestions():", err) + t.Fatal("Builder.StartQuestions() =", err) } for _, q := range msg.Questions { if err := b.Question(q); err != nil { - t.Fatalf("b.Question(%#v): %v", q, err) + t.Fatalf("Builder.Question(%#v) = %v", q, err) } } if err := b.StartAnswers(); err != nil { - t.Fatal("b.StartAnswers():", err) + t.Fatal("Builder.StartAnswers() =", err) } for _, a := range msg.Answers { switch a.Header.Type { case TypeA: if err := b.AResource(a.Header, *a.Body.(*AResource)); err != nil { - t.Fatalf("b.AResource(%#v): %v", a, err) + t.Fatalf("Builder.AResource(%#v) = %v", a, err) } case TypeNS: if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil { - t.Fatalf("b.NSResource(%#v): %v", a, err) + t.Fatalf("Builder.NSResource(%#v) = %v", a, err) } case TypeCNAME: if err := b.CNAMEResource(a.Header, *a.Body.(*CNAMEResource)); err != nil { - t.Fatalf("b.CNAMEResource(%#v): %v", a, err) + t.Fatalf("Builder.CNAMEResource(%#v) = %v", a, err) } case TypeSOA: if err := b.SOAResource(a.Header, *a.Body.(*SOAResource)); err != nil { - t.Fatalf("b.SOAResource(%#v): %v", a, err) + t.Fatalf("Builder.SOAResource(%#v) = %v", a, err) } case TypePTR: if err := b.PTRResource(a.Header, *a.Body.(*PTRResource)); err != nil { - t.Fatalf("b.PTRResource(%#v): %v", a, err) + t.Fatalf("Builder.PTRResource(%#v) = %v", a, err) } case TypeMX: if err := b.MXResource(a.Header, *a.Body.(*MXResource)); err != nil { - t.Fatalf("b.MXResource(%#v): %v", a, err) + t.Fatalf("Builder.MXResource(%#v) = %v", a, err) } case TypeTXT: if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil { - t.Fatalf("b.TXTResource(%#v): %v", a, err) + t.Fatalf("Builder.TXTResource(%#v) = %v", a, err) } case TypeAAAA: if err := b.AAAAResource(a.Header, *a.Body.(*AAAAResource)); err != nil { - t.Fatalf("b.AAAAResource(%#v): %v", a, err) + t.Fatalf("Builder.AAAAResource(%#v) = %v", a, err) } case TypeSRV: if err := b.SRVResource(a.Header, *a.Body.(*SRVResource)); err != nil { - t.Fatalf("b.SRVResource(%#v): %v", a, err) + t.Fatalf("Builder.SRVResource(%#v) = %v", a, err) } } } if err := b.StartAuthorities(); err != nil { - t.Fatal("b.StartAuthorities():", err) + t.Fatal("Builder.StartAuthorities() =", err) } for _, a := range msg.Authorities { if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil { - t.Fatalf("b.NSResource(%#v): %v", a, err) + t.Fatalf("Builder.NSResource(%#v) = %v", a, err) } } if err := b.StartAdditionals(); err != nil { - t.Fatal("b.StartAdditionals():", err) + t.Fatal("Builder.StartAdditionals() =", err) } for _, a := range msg.Additionals { - if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil { - t.Fatalf("b.TXTResource(%#v): %v", a, err) + switch a.Body.(type) { + case *TXTResource: + if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil { + t.Fatalf("Builder.TXTResource(%#v) = %v", a, err) + } + case *OPTResource: + if err := b.OPTResource(a.Header, *a.Body.(*OPTResource)); err != nil { + t.Fatalf("Builder.OPTResource(%#v) = %v", a, err) + } } } got, err := b.Finish() if err != nil { - t.Fatal("b.Finish():", err) + t.Fatal("Builder.Finish() =", err) } if !bytes.Equal(got, want) { - t.Fatalf("Got from Builder: %#v\nwant = %#v", got, want) + t.Fatalf("got from Builder.Finish() = %#v\nwant = %#v", got, want) } } @@ -606,7 +799,7 @@ Message{ Questions: []Question{ { - Name: mustNewName("."), + Name: MustNewName("."), Type: TypeAAAA, Class: ClassINET, }, @@ -619,7 +812,7 @@ Message{ Questions: []Question{ { - Name: mustNewName("."), + Name: MustNewName("."), Type: TypeAAAA, Class: ClassINET, }, @@ -636,7 +829,7 @@ Message{ Questions: []Question{ { - Name: mustNewName("."), + Name: MustNewName("."), Type: TypeA, Class: ClassINET, }, @@ -648,15 +841,202 @@ } { _, err := tt.m.Pack() if !reflect.DeepEqual(err, tt.err) { - t.Errorf("got %v for %v; want %v", err, tt.m, tt.err) + t.Errorf("got Message{%v}.Pack() = %v, want %v", tt.m, err, tt.err) } } } -func BenchmarkParsing(b *testing.B) { - b.ReportAllocs() +func TestResourcePackLength(t *testing.T) { + r := Resource{ + ResourceHeader{ + Name: MustNewName("."), + Type: TypeA, + Class: ClassINET, + }, + &AResource{[4]byte{127, 0, 0, 2}}, + } + + hb, _, err := r.Header.pack(nil, nil, 0) + if err != nil { + t.Fatal("ResourceHeader.pack() =", err) + } + buf := make([]byte, 0, len(hb)) + buf, err = r.pack(buf, nil, 0) + if err != nil { + t.Fatal("Resource.pack() =", err) + } + + var hdr ResourceHeader + if _, err := hdr.unpack(buf, 0); err != nil { + t.Fatal("ResourceHeader.unpack() =", err) + } + + if got, want := int(hdr.Length), len(buf)-len(hb); got != want { + t.Errorf("got hdr.Length = %d, want = %d", got, want) + } +} + +func TestOptionPackUnpack(t *testing.T) { + for _, tt := range []struct { + name string + w []byte // wire format of m.Additionals + m Message + dnssecOK bool + extRCode RCode + }{ + { + name: "without EDNS(0) options", + w: []byte{ + 0x00, 0x00, 0x29, 0x10, 0x00, 0xfe, 0x00, 0x80, + 0x00, 0x00, 0x00, + }, + m: Message{ + Header: Header{RCode: RCodeFormatError}, + Questions: []Question{ + { + Name: MustNewName("."), + Type: TypeA, + Class: ClassINET, + }, + }, + Additionals: []Resource{ + { + mustEDNS0ResourceHeader(4096, 0xfe0|RCodeFormatError, true), + &OPTResource{}, + }, + }, + }, + dnssecOK: true, + extRCode: 0xfe0 | RCodeFormatError, + }, + { + name: "with EDNS(0) options", + w: []byte{ + 0x00, 0x00, 0x29, 0x10, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x0b, 0x00, 0x02, 0x12, 0x34, + }, + m: Message{ + Header: Header{RCode: RCodeServerFailure}, + Questions: []Question{ + { + Name: MustNewName("."), + Type: TypeAAAA, + Class: ClassINET, + }, + }, + Additionals: []Resource{ + { + mustEDNS0ResourceHeader(4096, 0xff0|RCodeServerFailure, false), + &OPTResource{ + Options: []Option{ + { + Code: 12, // see RFC 7828 + Data: []byte{0x00, 0x00}, + }, + { + Code: 11, // see RFC 7830 + Data: []byte{0x12, 0x34}, + }, + }, + }, + }, + }, + }, + dnssecOK: false, + extRCode: 0xff0 | RCodeServerFailure, + }, + { + // Containing multiple OPT resources in a + // message is invalid, but it's necessary for + // protocol conformance testing. + name: "with multiple OPT resources", + w: []byte{ + 0x00, 0x00, 0x29, 0x10, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x02, 0x12, + 0x34, 0x00, 0x00, 0x29, 0x10, 0x00, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x02, + 0x00, 0x00, + }, + m: Message{ + Header: Header{RCode: RCodeNameError}, + Questions: []Question{ + { + Name: MustNewName("."), + Type: TypeAAAA, + Class: ClassINET, + }, + }, + Additionals: []Resource{ + { + mustEDNS0ResourceHeader(4096, 0xff0|RCodeNameError, false), + &OPTResource{ + Options: []Option{ + { + Code: 11, // see RFC 7830 + Data: []byte{0x12, 0x34}, + }, + }, + }, + }, + { + mustEDNS0ResourceHeader(4096, 0xff0|RCodeNameError, false), + &OPTResource{ + Options: []Option{ + { + Code: 12, // see RFC 7828 + Data: []byte{0x00, 0x00}, + }, + }, + }, + }, + }, + }, + }, + } { + w, err := tt.m.Pack() + if err != nil { + t.Errorf("Message.Pack() for %s = %v", tt.name, err) + continue + } + if !bytes.Equal(w[len(w)-len(tt.w):], tt.w) { + t.Errorf("got Message.Pack() for %s = %#v, want %#v", tt.name, w[len(w)-len(tt.w):], tt.w) + continue + } + var m Message + if err := m.Unpack(w); err != nil { + t.Errorf("Message.Unpack() for %s = %v", tt.name, err) + continue + } + if !reflect.DeepEqual(m.Additionals, tt.m.Additionals) { + t.Errorf("got Message.Pack/Unpack() roundtrip for %s = %+v, want %+v", tt.name, m, tt.m) + continue + } + } +} - name := mustNewName("foo.bar.example.com.") +// TestGoString tests that Message.GoString produces Go code that compiles to +// reproduce the Message. +// +// This test was produced as follows: +// 1. Run (*Message).GoString on largeTestMsg(). +// 2. Remove "dnsmessage." from the output. +// 3. Paste the result in the test to store it in msg. +// 4. Also put the original output in the test to store in want. +func TestGoString(t *testing.T) { + msg := Message{Header: Header{ID: 0, Response: true, OpCode: 0, Authoritative: true, Truncated: false, RecursionDesired: false, RecursionAvailable: false, RCode: RCodeSuccess}, Questions: []Question{{Name: MustNewName("foo.bar.example.com."), Type: TypeA, Class: ClassINET}}, Answers: []Resource{{Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeA, Class: ClassINET, TTL: 0, Length: 0}, Body: &AResource{A: [4]byte{127, 0, 0, 1}}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeA, Class: ClassINET, TTL: 0, Length: 0}, Body: &AResource{A: [4]byte{127, 0, 0, 2}}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeAAAA, Class: ClassINET, TTL: 0, Length: 0}, Body: &AAAAResource{AAAA: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeCNAME, Class: ClassINET, TTL: 0, Length: 0}, Body: &CNAMEResource{CNAME: MustNewName("alias.example.com.")}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeSOA, Class: ClassINET, TTL: 0, Length: 0}, Body: &SOAResource{NS: MustNewName("ns1.example.com."), MBox: MustNewName("mb.example.com."), Serial: 1, Refresh: 2, Retry: 3, Expire: 4, MinTTL: 5}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypePTR, Class: ClassINET, TTL: 0, Length: 0}, Body: &PTRResource{PTR: MustNewName("ptr.example.com.")}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeMX, Class: ClassINET, TTL: 0, Length: 0}, Body: &MXResource{Pref: 7, MX: MustNewName("mx.example.com.")}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeSRV, Class: ClassINET, TTL: 0, Length: 0}, Body: &SRVResource{Priority: 8, Weight: 9, Port: 11, Target: MustNewName("srv.example.com.")}}}, Authorities: []Resource{{Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeNS, Class: ClassINET, TTL: 0, Length: 0}, Body: &NSResource{NS: MustNewName("ns1.example.com.")}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeNS, Class: ClassINET, TTL: 0, Length: 0}, Body: &NSResource{NS: MustNewName("ns2.example.com.")}}}, Additionals: []Resource{{Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeTXT, Class: ClassINET, TTL: 0, Length: 0}, Body: &TXTResource{TXT: []string{"So Long\x2c and Thanks for All the Fish"}}}, {Header: ResourceHeader{Name: MustNewName("foo.bar.example.com."), Type: TypeTXT, Class: ClassINET, TTL: 0, Length: 0}, Body: &TXTResource{TXT: []string{"Hamster Huey and the Gooey Kablooie"}}}, {Header: ResourceHeader{Name: MustNewName("."), Type: TypeOPT, Class: 4096, TTL: 4261412864, Length: 0}, Body: &OPTResource{Options: []Option{{Code: 10, Data: []byte{1, 35, 69, 103, 137, 171, 205, 239}}}}}}} + if !reflect.DeepEqual(msg, largeTestMsg()) { + t.Error("Message.GoString lost information or largeTestMsg changed: msg != largeTestMsg()") + } + got := msg.GoString() + want := `dnsmessage.Message{Header: dnsmessage.Header{ID: 0, Response: true, OpCode: 0, Authoritative: true, Truncated: false, RecursionDesired: false, RecursionAvailable: false, RCode: dnsmessage.RCodeSuccess}, Questions: []dnsmessage.Question{dnsmessage.Question{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeA, Class: dnsmessage.ClassINET}}, Answers: []dnsmessage.Resource{dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeA, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 1}}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeA, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 2}}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeAAAA, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.AAAAResource{AAAA: [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeCNAME, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.CNAMEResource{CNAME: dnsmessage.MustNewName("alias.example.com.")}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeSOA, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.SOAResource{NS: dnsmessage.MustNewName("ns1.example.com."), MBox: dnsmessage.MustNewName("mb.example.com."), Serial: 1, Refresh: 2, Retry: 3, Expire: 4, MinTTL: 5}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypePTR, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.PTRResource{PTR: dnsmessage.MustNewName("ptr.example.com.")}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeMX, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.MXResource{Pref: 7, MX: dnsmessage.MustNewName("mx.example.com.")}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeSRV, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.SRVResource{Priority: 8, Weight: 9, Port: 11, Target: dnsmessage.MustNewName("srv.example.com.")}}}, Authorities: []dnsmessage.Resource{dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeNS, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.NSResource{NS: dnsmessage.MustNewName("ns1.example.com.")}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeNS, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.NSResource{NS: dnsmessage.MustNewName("ns2.example.com.")}}}, Additionals: []dnsmessage.Resource{dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeTXT, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.TXTResource{TXT: []string{"So Long\x2c and Thanks for All the Fish"}}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("foo.bar.example.com."), Type: dnsmessage.TypeTXT, Class: dnsmessage.ClassINET, TTL: 0, Length: 0}, Body: &dnsmessage.TXTResource{TXT: []string{"Hamster Huey and the Gooey Kablooie"}}}, dnsmessage.Resource{Header: dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName("."), Type: dnsmessage.TypeOPT, Class: 4096, TTL: 4261412864, Length: 0}, Body: &dnsmessage.OPTResource{Options: []dnsmessage.Option{dnsmessage.Option{Code: 10, Data: []byte{1, 35, 69, 103, 137, 171, 205, 239}}}}}}}` + if got != want { + t.Errorf("got msg1.GoString() = %s\nwant = %s", got, want) + } +} + +func benchmarkParsingSetup() ([]byte, error) { + name := MustNewName("foo.bar.example.com.") msg := Message{ Header: Header{Response: true, Authoritative: true}, Questions: []Question{ @@ -700,116 +1080,166 @@ buf, err := msg.Pack() if err != nil { - b.Fatal("msg.Pack():", err) + return nil, fmt.Errorf("Message.Pack() = %v", err) } + return buf, nil +} - for i := 0; i < b.N; i++ { - var p Parser - if _, err := p.Start(buf); err != nil { - b.Fatal("p.Start(buf):", err) +func benchmarkParsing(tb testing.TB, buf []byte) { + var p Parser + if _, err := p.Start(buf); err != nil { + tb.Fatal("Parser.Start(non-nil) =", err) + } + + for { + _, err := p.Question() + if err == ErrSectionDone { + break + } + if err != nil { + tb.Fatal("Parser.Question() =", err) } + } - for { - _, err := p.Question() - if err == ErrSectionDone { - break - } - if err != nil { - b.Fatal("p.Question():", err) - } + for { + h, err := p.AnswerHeader() + if err == ErrSectionDone { + break + } + if err != nil { + tb.Fatal("Parser.AnswerHeader() =", err) } - for { - h, err := p.AnswerHeader() - if err == ErrSectionDone { - break + switch h.Type { + case TypeA: + if _, err := p.AResource(); err != nil { + tb.Fatal("Parser.AResource() =", err) } - if err != nil { - panic(err) + case TypeAAAA: + if _, err := p.AAAAResource(); err != nil { + tb.Fatal("Parser.AAAAResource() =", err) } - - switch h.Type { - case TypeA: - if _, err := p.AResource(); err != nil { - b.Fatal("p.AResource():", err) - } - case TypeAAAA: - if _, err := p.AAAAResource(); err != nil { - b.Fatal("p.AAAAResource():", err) - } - case TypeCNAME: - if _, err := p.CNAMEResource(); err != nil { - b.Fatal("p.CNAMEResource():", err) - } - case TypeNS: - if _, err := p.NSResource(); err != nil { - b.Fatal("p.NSResource():", err) - } - default: - b.Fatalf("unknown type: %T", h) + case TypeCNAME: + if _, err := p.CNAMEResource(); err != nil { + tb.Fatal("Parser.CNAMEResource() =", err) + } + case TypeNS: + if _, err := p.NSResource(); err != nil { + tb.Fatal("Parser.NSResource() =", err) } + case TypeOPT: + if _, err := p.OPTResource(); err != nil { + tb.Fatal("Parser.OPTResource() =", err) + } + default: + tb.Fatalf("got unknown type: %T", h) } } } -func BenchmarkBuilding(b *testing.B) { +func BenchmarkParsing(b *testing.B) { + buf, err := benchmarkParsingSetup() + if err != nil { + b.Fatal(err) + } + b.ReportAllocs() + for i := 0; i < b.N; i++ { + benchmarkParsing(b, buf) + } +} + +func TestParsingAllocs(t *testing.T) { + buf, err := benchmarkParsingSetup() + if err != nil { + t.Fatal(err) + } + + if allocs := testing.AllocsPerRun(100, func() { benchmarkParsing(t, buf) }); allocs > 0.5 { + t.Errorf("allocations during parsing: got = %f, want ~0", allocs) + } +} - name := mustNewName("foo.bar.example.com.") +func benchmarkBuildingSetup() (Name, []byte) { + name := MustNewName("foo.bar.example.com.") buf := make([]byte, 0, packStartingCap) + return name, buf +} - for i := 0; i < b.N; i++ { - var bld Builder - bld.StartWithoutCompression(buf, Header{Response: true, Authoritative: true}) +func benchmarkBuilding(tb testing.TB, name Name, buf []byte) { + bld := NewBuilder(buf, Header{Response: true, Authoritative: true}) - if err := bld.StartQuestions(); err != nil { - b.Fatal("bld.StartQuestions():", err) - } - q := Question{ - Name: name, - Type: TypeA, - Class: ClassINET, - } - if err := bld.Question(q); err != nil { - b.Fatalf("bld.Question(%+v): %v", q, err) - } + if err := bld.StartQuestions(); err != nil { + tb.Fatal("Builder.StartQuestions() =", err) + } + q := Question{ + Name: name, + Type: TypeA, + Class: ClassINET, + } + if err := bld.Question(q); err != nil { + tb.Fatalf("Builder.Question(%+v) = %v", q, err) + } - hdr := ResourceHeader{ - Name: name, - Class: ClassINET, - } - if err := bld.StartAnswers(); err != nil { - b.Fatal("bld.StartQuestions():", err) - } + hdr := ResourceHeader{ + Name: name, + Class: ClassINET, + } + if err := bld.StartAnswers(); err != nil { + tb.Fatal("Builder.StartQuestions() =", err) + } - ar := AResource{[4]byte{}} - if err := bld.AResource(hdr, ar); err != nil { - b.Fatalf("bld.AResource(%+v, %+v): %v", hdr, ar, err) - } + ar := AResource{[4]byte{}} + if err := bld.AResource(hdr, ar); err != nil { + tb.Fatalf("Builder.AResource(%+v, %+v) = %v", hdr, ar, err) + } - aaar := AAAAResource{[16]byte{}} - if err := bld.AAAAResource(hdr, aaar); err != nil { - b.Fatalf("bld.AAAAResource(%+v, %+v): %v", hdr, aaar, err) - } + aaar := AAAAResource{[16]byte{}} + if err := bld.AAAAResource(hdr, aaar); err != nil { + tb.Fatalf("Builder.AAAAResource(%+v, %+v) = %v", hdr, aaar, err) + } - cnr := CNAMEResource{name} - if err := bld.CNAMEResource(hdr, cnr); err != nil { - b.Fatalf("bld.CNAMEResource(%+v, %+v): %v", hdr, cnr, err) - } + cnr := CNAMEResource{name} + if err := bld.CNAMEResource(hdr, cnr); err != nil { + tb.Fatalf("Builder.CNAMEResource(%+v, %+v) = %v", hdr, cnr, err) + } - nsr := NSResource{name} - if err := bld.NSResource(hdr, nsr); err != nil { - b.Fatalf("bld.NSResource(%+v, %+v): %v", hdr, nsr, err) - } + nsr := NSResource{name} + if err := bld.NSResource(hdr, nsr); err != nil { + tb.Fatalf("Builder.NSResource(%+v, %+v) = %v", hdr, nsr, err) + } - if _, err := bld.Finish(); err != nil { - b.Fatal("bld.Finish():", err) - } + extrc := 0xfe0 | RCodeNotImplemented + if err := (&hdr).SetEDNS0(4096, extrc, true); err != nil { + tb.Fatalf("ResourceHeader.SetEDNS0(4096, %#x, true) = %v", extrc, err) + } + optr := OPTResource{} + if err := bld.OPTResource(hdr, optr); err != nil { + tb.Fatalf("Builder.OPTResource(%+v, %+v) = %v", hdr, optr, err) + } + + if _, err := bld.Finish(); err != nil { + tb.Fatal("Builder.Finish() =", err) + } +} + +func BenchmarkBuilding(b *testing.B) { + name, buf := benchmarkBuildingSetup() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + benchmarkBuilding(b, name, buf) + } +} + +func TestBuildingAllocs(t *testing.T) { + name, buf := benchmarkBuildingSetup() + if allocs := testing.AllocsPerRun(100, func() { benchmarkBuilding(t, name, buf) }); allocs > 0.5 { + t.Errorf("allocations during building: got = %f, want ~0", allocs) } } func smallTestMsg() Message { - name := mustNewName("example.com.") + name := MustNewName("example.com.") return Message{ Header: Header{Response: true, Authoritative: true}, Questions: []Question{ @@ -859,7 +1289,7 @@ for i := 0; i < b.N; i++ { if _, err := msg.Pack(); err != nil { - b.Fatal(err) + b.Fatal("Message.Pack() =", err) } } } @@ -872,13 +1302,13 @@ for i := 0; i < b.N; i++ { if _, err := msg.AppendPack(buf[:0]); err != nil { - b.Fatal(err) + b.Fatal("Message.AppendPack() = ", err) } } } func largeTestMsg() Message { - name := mustNewName("foo.bar.example.com.") + name := MustNewName("foo.bar.example.com.") return Message{ Header: Header{Response: true, Authoritative: true}, Questions: []Question{ @@ -919,7 +1349,7 @@ Type: TypeCNAME, Class: ClassINET, }, - &CNAMEResource{mustNewName("alias.example.com.")}, + &CNAMEResource{MustNewName("alias.example.com.")}, }, { ResourceHeader{ @@ -928,8 +1358,8 @@ Class: ClassINET, }, &SOAResource{ - NS: mustNewName("ns1.example.com."), - MBox: mustNewName("mb.example.com."), + NS: MustNewName("ns1.example.com."), + MBox: MustNewName("mb.example.com."), Serial: 1, Refresh: 2, Retry: 3, @@ -943,7 +1373,7 @@ Type: TypePTR, Class: ClassINET, }, - &PTRResource{mustNewName("ptr.example.com.")}, + &PTRResource{MustNewName("ptr.example.com.")}, }, { ResourceHeader{ @@ -953,7 +1383,7 @@ }, &MXResource{ 7, - mustNewName("mx.example.com."), + MustNewName("mx.example.com."), }, }, { @@ -966,7 +1396,7 @@ 8, 9, 11, - mustNewName("srv.example.com."), + MustNewName("srv.example.com."), }, }, }, @@ -977,7 +1407,7 @@ Type: TypeNS, Class: ClassINET, }, - &NSResource{mustNewName("ns1.example.com.")}, + &NSResource{MustNewName("ns1.example.com.")}, }, { ResourceHeader{ @@ -985,7 +1415,7 @@ Type: TypeNS, Class: ClassINET, }, - &NSResource{mustNewName("ns2.example.com.")}, + &NSResource{MustNewName("ns2.example.com.")}, }, }, Additionals: []Resource{ @@ -995,7 +1425,7 @@ Type: TypeTXT, Class: ClassINET, }, - &TXTResource{"So Long, and Thanks for All the Fish"}, + &TXTResource{[]string{"So Long, and Thanks for All the Fish"}}, }, { ResourceHeader{ @@ -1003,139 +1433,19 @@ Type: TypeTXT, Class: ClassINET, }, - &TXTResource{"Hamster Huey and the Gooey Kablooie"}, + &TXTResource{[]string{"Hamster Huey and the Gooey Kablooie"}}, + }, + { + mustEDNS0ResourceHeader(4096, 0xfe0|RCodeSuccess, false), + &OPTResource{ + Options: []Option{ + { + Code: 10, // see RFC 7873 + Data: []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + }, + }, + }, }, }, } } - -const loremIpsum = ` -Lorem ipsum dolor sit amet, nec enim antiopam id, an ullum choro -nonumes qui, pro eu debet honestatis mediocritatem. No alia enim eos, -magna signiferumque ex vis. Mei no aperiri dissentias, cu vel quas -regione. Malorum quaeque vim ut, eum cu semper aliquid invidunt, ei -nam ipsum assentior. - -Nostrum appellantur usu no, vis ex probatus adipiscing. Cu usu illum -facilis eleifend. Iusto conceptam complectitur vim id. Tale omnesque -no usu, ei oblique sadipscing vim. At nullam voluptua usu, mei laudem -reformidans et. Qui ei eros porro reformidans, ius suas veritus -torquatos ex. Mea te facer alterum consequat. - -Soleat torquatos democritum sed et, no mea congue appareat, facer -aliquam nec in. Has te ipsum tritani. At justo dicta option nec, movet -phaedrum ad nam. Ea detracto verterem liberavisse has, delectus -suscipiantur in mei. Ex nam meliore complectitur. Ut nam omnis -honestatis quaerendum, ea mea nihil affert detracto, ad vix rebum -mollis. - -Ut epicurei praesent neglegentur pri, prima fuisset intellegebat ad -vim. An habemus comprehensam usu, at enim dignissim pro. Eam reque -vivendum adipisci ea. Vel ne odio choro minimum. Sea admodum -dissentiet ex. Mundi tamquam evertitur ius cu. Homero postea iisque ut -pro, vel ne saepe senserit consetetur. - -Nulla utamur facilisis ius ea, in viderer diceret pertinax eum. Mei no -enim quodsi facilisi, ex sed aeterno appareat mediocritatem, eum -sententiae deterruisset ut. At suas timeam euismod cum, offendit -appareat interpretaris ne vix. Vel ea civibus albucius, ex vim quidam -accusata intellegebat, noluisse instructior sea id. Nec te nonumes -habemus appellantur, quis dignissim vituperata eu nam. - -At vix apeirian patrioque vituperatoribus, an usu agam assum. Debet -iisque an mea. Per eu dicant ponderum accommodare. Pri alienum -placerat senserit an, ne eum ferri abhorreant vituperatoribus. Ut mea -eligendi disputationi. Ius no tation everti impedit, ei magna quidam -mediocritatem pri. - -Legendos perpetua iracundia ne usu, no ius ullum epicurei intellegam, -ad modus epicuri lucilius eam. In unum quaerendum usu. Ne diam paulo -has, ea veri virtute sed. Alia honestatis conclusionemque mea eu, ut -iudico albucius his. - -Usu essent probatus eu, sed omnis dolor delicatissimi ex. No qui augue -dissentias dissentiet. Laudem recteque no usu, vel an velit noluisse, -an sed utinam eirmod appetere. Ne mea fuisset inimicus ocurreret. At -vis dicant abhorreant, utinam forensibus nec ne, mei te docendi -consequat. Brute inermis persecuti cum id. Ut ipsum munere propriae -usu, dicit graeco disputando id has. - -Eros dolore quaerendum nam ei. Timeam ornatus inciderint pro id. Nec -torquatos sadipscing ei, ancillae molestie per in. Malis principes duo -ea, usu liber postulant ei. - -Graece timeam voluptatibus eu eam. Alia probatus quo no, ea scripta -feugiat duo. Congue option meliore ex qui, noster invenire appellantur -ea vel. Eu exerci legendos vel. Consetetur repudiandae vim ut. Vix an -probo minimum, et nam illud falli tempor. - -Cum dico signiferumque eu. Sed ut regione maiorum, id veritus insolens -tacimates vix. Eu mel sint tamquam lucilius, duo no oporteat -tacimates. Atqui augue concludaturque vix ei, id mel utroque menandri. - -Ad oratio blandit aliquando pro. Vis et dolorum rationibus -philosophia, ad cum nulla molestie. Hinc fuisset adversarium eum et, -ne qui nisl verear saperet, vel te quaestio forensibus. Per odio -option delenit an. Alii placerat has no, in pri nihil platonem -cotidieque. Est ut elit copiosae scaevola, debet tollit maluisset sea -an. - -Te sea hinc debet pericula, liber ridens fabulas cu sed, quem mutat -accusam mea et. Elitr labitur albucius et pri, an labore feugait mel. -Velit zril melius usu ea. Ad stet putent interpretaris qui. Mel no -error volumus scripserit. In pro paulo iudico, quo ei dolorem -verterem, affert fabellas dissentiet ea vix. - -Vis quot deserunt te. Error aliquid detraxit eu usu, vis alia eruditi -salutatus cu. Est nostrud bonorum an, ei usu alii salutatus. Vel at -nisl primis, eum ex aperiri noluisse reformidans. Ad veri velit -utroque vis, ex equidem detraxit temporibus has. - -Inermis appareat usu ne. Eros placerat periculis mea ad, in dictas -pericula pro. Errem postulant at usu, ea nec amet ornatus mentitum. Ad -mazim graeco eum, vel ex percipit volutpat iudicabit, sit ne delicata -interesset. Mel sapientem prodesset abhorreant et, oblique suscipit -eam id. - -An maluisset disputando mea, vidit mnesarchum pri et. Malis insolens -inciderint no sea. Ea persius maluisset vix, ne vim appellantur -instructior, consul quidam definiebas pri id. Cum integre feugiat -pericula in, ex sed persius similique, mel ne natum dicit percipitur. - -Primis discere ne pri, errem putent definitionem at vis. Ei mel dolore -neglegentur, mei tincidunt percipitur ei. Pro ad simul integre -rationibus. Eu vel alii honestatis definitiones, mea no nonumy -reprehendunt. - -Dicta appareat legendos est cu. Eu vel congue dicunt omittam, no vix -adhuc minimum constituam, quot noluisse id mel. Eu quot sale mutat -duo, ex nisl munere invenire duo. Ne nec ullum utamur. Pro alterum -debitis nostrum no, ut vel aliquid vivendo. - -Aliquip fierent praesent quo ne, id sit audiam recusabo delicatissimi. -Usu postulant incorrupte cu. At pro dicit tibique intellegam, cibo -dolore impedit id eam, et aeque feugait assentior has. Quando sensibus -nec ex. Possit sensibus pri ad, unum mutat periculis cu vix. - -Mundi tibique vix te, duo simul partiendo qualisque id, est at vidit -sonet tempor. No per solet aeterno deseruisse. Petentium salutandi -definiebas pri cu. Munere vivendum est in. Ei justo congue eligendi -vis, modus offendit omittantur te mel. - -Integre voluptaria in qui, sit habemus tractatos constituam no. Utinam -melius conceptam est ne, quo in minimum apeirian delicata, ut ius -porro recusabo. Dicant expetenda vix no, ludus scripserit sed ex, eu -his modo nostro. Ut etiam sonet his, quodsi inciderint philosophia te -per. Nullam lobortis eu cum, vix an sonet efficiendi repudiandae. Vis -ad idque fabellas intellegebat. - -Eum commodo senserit conclusionemque ex. Sed forensibus sadipscing ut, -mei in facer delicata periculis, sea ne hinc putent cetero. Nec ne -alia corpora invenire, alia prima soleat te cum. Eleifend posidonium -nam at. - -Dolorum indoctum cu quo, ex dolor legendos recteque eam, cu pri zril -discere. Nec civibus officiis dissentiunt ex, est te liber ludus -elaboraret. Cum ea fabellas invenire. Ex vim nostrud eripuit -comprehensam, nam te inermis delectus, saepe inermis senserit. -` diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/go.mod golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/go.mod --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/go.mod 1970-01-01 00:00:00.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/go.mod 2019-08-17 11:56:26.000000000 +0000 @@ -0,0 +1,9 @@ +module golang.org/x/net + +go 1.11 + +require ( + golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 + golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a + golang.org/x/text v0.3.0 +) diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/go.sum golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/go.sum --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/go.sum 1970-01-01 00:00:00.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/go.sum 2019-08-17 11:56:26.000000000 +0000 @@ -0,0 +1,6 @@ +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/atom/gen.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/atom/gen.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/atom/gen.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/atom/gen.go 2019-08-17 11:56:26.000000000 +0000 @@ -306,7 +306,7 @@ // The lists of element names and attribute keys were taken from // https://html.spec.whatwg.org/multipage/indices.html#index -// as of the "HTML Living Standard - Last Updated 18 September 2017" version. +// as of the "HTML Living Standard - Last Updated 16 April 2018" version. // "command", "keygen" and "menuitem" have been removed from the spec, // but are kept here for backwards compatibility. @@ -665,6 +665,7 @@ // extra are ad-hoc values not covered by any of the lists above. var extra = []string{ + "acronym", "align", "annotation", "annotation-xml", @@ -700,6 +701,8 @@ "plaintext", "prompt", "public", + "rb", + "rtc", "spacer", "strike", "svg", diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/atom/table.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/atom/table.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/atom/table.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/atom/table.go 2019-08-17 11:56:26.000000000 +0000 @@ -10,366 +10,369 @@ Accept Atom = 0x1a06 AcceptCharset Atom = 0x1a0e Accesskey Atom = 0x2c09 - Action Atom = 0x25a06 - Address Atom = 0x6ed07 - Align Atom = 0x6d405 - Allowfullscreen Atom = 0x1f00f - Allowpaymentrequest Atom = 0x6913 - Allowusermedia Atom = 0x850e - Alt Atom = 0xb003 - Annotation Atom = 0x1b90a - AnnotationXml Atom = 0x1b90e - Applet Atom = 0x30106 - Area Atom = 0x34a04 - Article Atom = 0x3f007 - As Atom = 0xb902 - Aside Atom = 0xc105 - Async Atom = 0xb905 - Audio Atom = 0xcf05 - Autocomplete Atom = 0x2600c - Autofocus Atom = 0xeb09 - Autoplay Atom = 0x10608 + Acronym Atom = 0xaa07 + Action Atom = 0x27206 + Address Atom = 0x6f307 + Align Atom = 0xb105 + Allowfullscreen Atom = 0x2080f + Allowpaymentrequest Atom = 0xc113 + Allowusermedia Atom = 0xdd0e + Alt Atom = 0xf303 + Annotation Atom = 0x1c90a + AnnotationXml Atom = 0x1c90e + Applet Atom = 0x31906 + Area Atom = 0x35604 + Article Atom = 0x3fc07 + As Atom = 0x3c02 + Aside Atom = 0x10705 + Async Atom = 0xff05 + Audio Atom = 0x11505 + Autocomplete Atom = 0x2780c + Autofocus Atom = 0x12109 + Autoplay Atom = 0x13c08 B Atom = 0x101 - Base Atom = 0x11504 - Basefont Atom = 0x11508 - Bdi Atom = 0x16103 - Bdo Atom = 0x13403 - Bgsound Atom = 0x14707 - Big Atom = 0x15903 - Blink Atom = 0x15c05 - Blockquote Atom = 0x1680a + Base Atom = 0x3b04 + Basefont Atom = 0x3b08 + Bdi Atom = 0xba03 + Bdo Atom = 0x14b03 + Bgsound Atom = 0x15e07 + Big Atom = 0x17003 + Blink Atom = 0x17305 + Blockquote Atom = 0x1870a Body Atom = 0x2804 Br Atom = 0x202 - Button Atom = 0x17206 - Canvas Atom = 0xbd06 - Caption Atom = 0x21907 - Center Atom = 0x20806 - Challenge Atom = 0x28309 + Button Atom = 0x19106 + Canvas Atom = 0x10306 + Caption Atom = 0x23107 + Center Atom = 0x22006 + Challenge Atom = 0x29b09 Charset Atom = 0x2107 - Checked Atom = 0x46d07 - Cite Atom = 0x55804 - Class Atom = 0x5b905 - Code Atom = 0x19004 - Col Atom = 0x19703 - Colgroup Atom = 0x19708 - Color Atom = 0x1af05 - Cols Atom = 0x1b404 - Colspan Atom = 0x1b407 - Command Atom = 0x1c707 - Content Atom = 0x57f07 - Contenteditable Atom = 0x57f0f - Contextmenu Atom = 0x3740b - Controls Atom = 0x1ce08 - Coords Atom = 0x1da06 - Crossorigin Atom = 0x1e30b - Data Atom = 0x49904 - Datalist Atom = 0x49908 - Datetime Atom = 0x2a008 - Dd Atom = 0x2bf02 - Default Atom = 0xc407 - Defer Atom = 0x19205 - Del Atom = 0x44603 - Desc Atom = 0x55504 - Details Atom = 0x4607 - Dfn Atom = 0x5f03 - Dialog Atom = 0x16206 - Dir Atom = 0xa303 - Dirname Atom = 0xa307 - Disabled Atom = 0x14d08 - Div Atom = 0x15403 - Dl Atom = 0x5e202 - Download Atom = 0x45708 - Draggable Atom = 0x18309 - Dropzone Atom = 0x3f908 - Dt Atom = 0x64702 - Em Atom = 0x4202 - Embed Atom = 0x4205 - Enctype Atom = 0x27507 - Face Atom = 0x20604 - Fieldset Atom = 0x20e08 - Figcaption Atom = 0x2160a - Figure Atom = 0x23006 - Font Atom = 0x11904 - Footer Atom = 0xb306 - For Atom = 0x23c03 - ForeignObject Atom = 0x23c0d - Foreignobject Atom = 0x2490d - Form Atom = 0x25604 - Formaction Atom = 0x2560a - Formenctype Atom = 0x2710b - Formmethod Atom = 0x28c0a - Formnovalidate Atom = 0x2960e - Formtarget Atom = 0x2a80a - Frame Atom = 0x5705 - Frameset Atom = 0x5708 - H1 Atom = 0x14502 - H2 Atom = 0x2c602 - H3 Atom = 0x2f502 - H4 Atom = 0x33902 - H5 Atom = 0x34302 - H6 Atom = 0x64902 - Head Atom = 0x32504 - Header Atom = 0x32506 - Headers Atom = 0x32507 - Height Atom = 0x12c06 - Hgroup Atom = 0x2b206 - Hidden Atom = 0x2bd06 - High Atom = 0x2c304 - Hr Atom = 0x14002 - Href Atom = 0x2c804 - Hreflang Atom = 0x2c808 - Html Atom = 0x13004 - HttpEquiv Atom = 0x2d00a + Checked Atom = 0x47907 + Cite Atom = 0x19c04 + Class Atom = 0x56405 + Code Atom = 0x5c504 + Col Atom = 0x1ab03 + Colgroup Atom = 0x1ab08 + Color Atom = 0x1bf05 + Cols Atom = 0x1c404 + Colspan Atom = 0x1c407 + Command Atom = 0x1d707 + Content Atom = 0x58b07 + Contenteditable Atom = 0x58b0f + Contextmenu Atom = 0x3800b + Controls Atom = 0x1de08 + Coords Atom = 0x1ea06 + Crossorigin Atom = 0x1fb0b + Data Atom = 0x4a504 + Datalist Atom = 0x4a508 + Datetime Atom = 0x2b808 + Dd Atom = 0x2d702 + Default Atom = 0x10a07 + Defer Atom = 0x5c705 + Del Atom = 0x45203 + Desc Atom = 0x56104 + Details Atom = 0x7207 + Dfn Atom = 0x8703 + Dialog Atom = 0xbb06 + Dir Atom = 0x9303 + Dirname Atom = 0x9307 + Disabled Atom = 0x16408 + Div Atom = 0x16b03 + Dl Atom = 0x5e602 + Download Atom = 0x46308 + Draggable Atom = 0x17a09 + Dropzone Atom = 0x40508 + Dt Atom = 0x64b02 + Em Atom = 0x6e02 + Embed Atom = 0x6e05 + Enctype Atom = 0x28d07 + Face Atom = 0x21e04 + Fieldset Atom = 0x22608 + Figcaption Atom = 0x22e0a + Figure Atom = 0x24806 + Font Atom = 0x3f04 + Footer Atom = 0xf606 + For Atom = 0x25403 + ForeignObject Atom = 0x2540d + Foreignobject Atom = 0x2610d + Form Atom = 0x26e04 + Formaction Atom = 0x26e0a + Formenctype Atom = 0x2890b + Formmethod Atom = 0x2a40a + Formnovalidate Atom = 0x2ae0e + Formtarget Atom = 0x2c00a + Frame Atom = 0x8b05 + Frameset Atom = 0x8b08 + H1 Atom = 0x15c02 + H2 Atom = 0x2de02 + H3 Atom = 0x30d02 + H4 Atom = 0x34502 + H5 Atom = 0x34f02 + H6 Atom = 0x64d02 + Head Atom = 0x33104 + Header Atom = 0x33106 + Headers Atom = 0x33107 + Height Atom = 0x5206 + Hgroup Atom = 0x2ca06 + Hidden Atom = 0x2d506 + High Atom = 0x2db04 + Hr Atom = 0x15702 + Href Atom = 0x2e004 + Hreflang Atom = 0x2e008 + Html Atom = 0x5604 + HttpEquiv Atom = 0x2e80a I Atom = 0x601 - Icon Atom = 0x57e04 - Id Atom = 0xc302 - Iframe Atom = 0x2e406 - Image Atom = 0x2ea05 - Img Atom = 0x2ef03 - Input Atom = 0x43f05 - Inputmode Atom = 0x43f09 - Ins Atom = 0x1ec03 - Integrity Atom = 0x22709 - Is Atom = 0x14e02 - Isindex Atom = 0x2f707 - Ismap Atom = 0x2fe05 - Itemid Atom = 0x37f06 - Itemprop Atom = 0x55908 - Itemref Atom = 0x3c107 - Itemscope Atom = 0x66d09 - Itemtype Atom = 0x30708 - Kbd Atom = 0x16003 + Icon Atom = 0x58a04 + Id Atom = 0x10902 + Iframe Atom = 0x2fc06 + Image Atom = 0x30205 + Img Atom = 0x30703 + Input Atom = 0x44b05 + Inputmode Atom = 0x44b09 + Ins Atom = 0x20403 + Integrity Atom = 0x23f09 + Is Atom = 0x16502 + Isindex Atom = 0x30f07 + Ismap Atom = 0x31605 + Itemid Atom = 0x38b06 + Itemprop Atom = 0x19d08 + Itemref Atom = 0x3cd07 + Itemscope Atom = 0x67109 + Itemtype Atom = 0x31f08 + Kbd Atom = 0xb903 Keygen Atom = 0x3206 - Keytype Atom = 0x7e07 - Kind Atom = 0x18004 - Label Atom = 0xda05 - Lang Atom = 0x2cc04 - Legend Atom = 0x18a06 - Li Atom = 0x11102 - Link Atom = 0x15d04 - List Atom = 0x49d04 - Listing Atom = 0x49d07 - Loop Atom = 0xde04 - Low Atom = 0x6b03 + Keytype Atom = 0xd607 + Kind Atom = 0x17704 + Label Atom = 0x5905 + Lang Atom = 0x2e404 + Legend Atom = 0x18106 + Li Atom = 0xb202 + Link Atom = 0x17404 + List Atom = 0x4a904 + Listing Atom = 0x4a907 + Loop Atom = 0x5d04 + Low Atom = 0xc303 Main Atom = 0x1004 - Malignmark Atom = 0x6d30a - Manifest Atom = 0x30f08 - Map Atom = 0x30003 - Mark Atom = 0x6d904 - Marquee Atom = 0x31b07 - Math Atom = 0x32204 - Max Atom = 0x33103 - Maxlength Atom = 0x33109 - Media Atom = 0x8e05 - Mediagroup Atom = 0x8e0a - Menu Atom = 0x37b04 - Menuitem Atom = 0x37b08 - Meta Atom = 0x4ac04 - Meter Atom = 0xa805 - Method Atom = 0x29006 - Mglyph Atom = 0x2f006 - Mi Atom = 0x33b02 - Min Atom = 0x33b03 - Minlength Atom = 0x33b09 - Mn Atom = 0x29902 - Mo Atom = 0x6302 - Ms Atom = 0x67002 - Mtext Atom = 0x34505 - Multiple Atom = 0x35308 - Muted Atom = 0x35b05 - Name Atom = 0xa604 + Malignmark Atom = 0xb00a + Manifest Atom = 0x6d708 + Map Atom = 0x31803 + Mark Atom = 0xb604 + Marquee Atom = 0x32707 + Math Atom = 0x32e04 + Max Atom = 0x33d03 + Maxlength Atom = 0x33d09 + Media Atom = 0xe605 + Mediagroup Atom = 0xe60a + Menu Atom = 0x38704 + Menuitem Atom = 0x38708 + Meta Atom = 0x4b804 + Meter Atom = 0x9805 + Method Atom = 0x2a806 + Mglyph Atom = 0x30806 + Mi Atom = 0x34702 + Min Atom = 0x34703 + Minlength Atom = 0x34709 + Mn Atom = 0x2b102 + Mo Atom = 0xa402 + Ms Atom = 0x67402 + Mtext Atom = 0x35105 + Multiple Atom = 0x35f08 + Muted Atom = 0x36705 + Name Atom = 0x9604 Nav Atom = 0x1303 Nobr Atom = 0x3704 - Noembed Atom = 0x4007 - Noframes Atom = 0x5508 - Nomodule Atom = 0x6108 - Nonce Atom = 0x56205 - Noscript Atom = 0x1fe08 - Novalidate Atom = 0x29a0a - Object Atom = 0x25006 - Ol Atom = 0x10102 - Onabort Atom = 0x17607 - Onafterprint Atom = 0x21e0c - Onautocomplete Atom = 0x25e0e - Onautocompleteerror Atom = 0x25e13 - Onauxclick Atom = 0x61b0a - Onbeforeprint Atom = 0x69a0d - Onbeforeunload Atom = 0x6e10e - Onblur Atom = 0x5c206 - Oncancel Atom = 0xd308 - Oncanplay Atom = 0x13609 - Oncanplaythrough Atom = 0x13610 - Onchange Atom = 0x40f08 - Onclick Atom = 0x2dd07 - Onclose Atom = 0x36007 - Oncontextmenu Atom = 0x3720d - Oncopy Atom = 0x38506 - Oncuechange Atom = 0x38b0b - Oncut Atom = 0x39605 - Ondblclick Atom = 0x39b0a - Ondrag Atom = 0x3a506 - Ondragend Atom = 0x3a509 - Ondragenter Atom = 0x3ae0b - Ondragexit Atom = 0x3b90a - Ondragleave Atom = 0x3d30b - Ondragover Atom = 0x3de0a - Ondragstart Atom = 0x3e80b - Ondrop Atom = 0x3f706 - Ondurationchange Atom = 0x40710 - Onemptied Atom = 0x3fe09 - Onended Atom = 0x41707 - Onerror Atom = 0x41e07 - Onfocus Atom = 0x42507 - Onhashchange Atom = 0x4310c - Oninput Atom = 0x43d07 - Oninvalid Atom = 0x44909 - Onkeydown Atom = 0x45209 - Onkeypress Atom = 0x45f0a - Onkeyup Atom = 0x47407 - Onlanguagechange Atom = 0x48110 - Onload Atom = 0x49106 - Onloadeddata Atom = 0x4910c - Onloadedmetadata Atom = 0x4a410 - Onloadend Atom = 0x4ba09 - Onloadstart Atom = 0x4c30b - Onmessage Atom = 0x4ce09 - Onmessageerror Atom = 0x4ce0e - Onmousedown Atom = 0x4dc0b - Onmouseenter Atom = 0x4e70c - Onmouseleave Atom = 0x4f30c - Onmousemove Atom = 0x4ff0b - Onmouseout Atom = 0x50a0a - Onmouseover Atom = 0x5170b - Onmouseup Atom = 0x52209 - Onmousewheel Atom = 0x5300c - Onoffline Atom = 0x53c09 - Ononline Atom = 0x54508 - Onpagehide Atom = 0x54d0a - Onpageshow Atom = 0x5670a - Onpaste Atom = 0x57307 - Onpause Atom = 0x58e07 - Onplay Atom = 0x59806 - Onplaying Atom = 0x59809 - Onpopstate Atom = 0x5a10a - Onprogress Atom = 0x5ab0a - Onratechange Atom = 0x5c80c - Onrejectionhandled Atom = 0x5d412 - Onreset Atom = 0x5e607 - Onresize Atom = 0x5ed08 - Onscroll Atom = 0x5fc08 - Onsecuritypolicyviolation Atom = 0x60419 - Onseeked Atom = 0x62508 - Onseeking Atom = 0x62d09 - Onselect Atom = 0x63608 - Onshow Atom = 0x64006 - Onsort Atom = 0x64b06 - Onstalled Atom = 0x65509 - Onstorage Atom = 0x65e09 - Onsubmit Atom = 0x66708 - Onsuspend Atom = 0x67709 - Ontimeupdate Atom = 0x11a0c - Ontoggle Atom = 0x68008 - Onunhandledrejection Atom = 0x68814 - Onunload Atom = 0x6a708 - Onvolumechange Atom = 0x6af0e - Onwaiting Atom = 0x6bd09 - Onwheel Atom = 0x6c607 - Open Atom = 0x55f04 - Optgroup Atom = 0xe008 - Optimum Atom = 0x6cd07 - Option Atom = 0x6dd06 - Output Atom = 0x51106 + Noembed Atom = 0x6c07 + Noframes Atom = 0x8908 + Nomodule Atom = 0xa208 + Nonce Atom = 0x1a605 + Noscript Atom = 0x21608 + Novalidate Atom = 0x2b20a + Object Atom = 0x26806 + Ol Atom = 0x13702 + Onabort Atom = 0x19507 + Onafterprint Atom = 0x2360c + Onautocomplete Atom = 0x2760e + Onautocompleteerror Atom = 0x27613 + Onauxclick Atom = 0x61f0a + Onbeforeprint Atom = 0x69e0d + Onbeforeunload Atom = 0x6e70e + Onblur Atom = 0x56d06 + Oncancel Atom = 0x11908 + Oncanplay Atom = 0x14d09 + Oncanplaythrough Atom = 0x14d10 + Onchange Atom = 0x41b08 + Onclick Atom = 0x2f507 + Onclose Atom = 0x36c07 + Oncontextmenu Atom = 0x37e0d + Oncopy Atom = 0x39106 + Oncuechange Atom = 0x3970b + Oncut Atom = 0x3a205 + Ondblclick Atom = 0x3a70a + Ondrag Atom = 0x3b106 + Ondragend Atom = 0x3b109 + Ondragenter Atom = 0x3ba0b + Ondragexit Atom = 0x3c50a + Ondragleave Atom = 0x3df0b + Ondragover Atom = 0x3ea0a + Ondragstart Atom = 0x3f40b + Ondrop Atom = 0x40306 + Ondurationchange Atom = 0x41310 + Onemptied Atom = 0x40a09 + Onended Atom = 0x42307 + Onerror Atom = 0x42a07 + Onfocus Atom = 0x43107 + Onhashchange Atom = 0x43d0c + Oninput Atom = 0x44907 + Oninvalid Atom = 0x45509 + Onkeydown Atom = 0x45e09 + Onkeypress Atom = 0x46b0a + Onkeyup Atom = 0x48007 + Onlanguagechange Atom = 0x48d10 + Onload Atom = 0x49d06 + Onloadeddata Atom = 0x49d0c + Onloadedmetadata Atom = 0x4b010 + Onloadend Atom = 0x4c609 + Onloadstart Atom = 0x4cf0b + Onmessage Atom = 0x4da09 + Onmessageerror Atom = 0x4da0e + Onmousedown Atom = 0x4e80b + Onmouseenter Atom = 0x4f30c + Onmouseleave Atom = 0x4ff0c + Onmousemove Atom = 0x50b0b + Onmouseout Atom = 0x5160a + Onmouseover Atom = 0x5230b + Onmouseup Atom = 0x52e09 + Onmousewheel Atom = 0x53c0c + Onoffline Atom = 0x54809 + Ononline Atom = 0x55108 + Onpagehide Atom = 0x5590a + Onpageshow Atom = 0x5730a + Onpaste Atom = 0x57f07 + Onpause Atom = 0x59a07 + Onplay Atom = 0x5a406 + Onplaying Atom = 0x5a409 + Onpopstate Atom = 0x5ad0a + Onprogress Atom = 0x5b70a + Onratechange Atom = 0x5cc0c + Onrejectionhandled Atom = 0x5d812 + Onreset Atom = 0x5ea07 + Onresize Atom = 0x5f108 + Onscroll Atom = 0x60008 + Onsecuritypolicyviolation Atom = 0x60819 + Onseeked Atom = 0x62908 + Onseeking Atom = 0x63109 + Onselect Atom = 0x63a08 + Onshow Atom = 0x64406 + Onsort Atom = 0x64f06 + Onstalled Atom = 0x65909 + Onstorage Atom = 0x66209 + Onsubmit Atom = 0x66b08 + Onsuspend Atom = 0x67b09 + Ontimeupdate Atom = 0x400c + Ontoggle Atom = 0x68408 + Onunhandledrejection Atom = 0x68c14 + Onunload Atom = 0x6ab08 + Onvolumechange Atom = 0x6b30e + Onwaiting Atom = 0x6c109 + Onwheel Atom = 0x6ca07 + Open Atom = 0x1a304 + Optgroup Atom = 0x5f08 + Optimum Atom = 0x6d107 + Option Atom = 0x6e306 + Output Atom = 0x51d06 P Atom = 0xc01 Param Atom = 0xc05 - Pattern Atom = 0x4f07 - Picture Atom = 0x9707 - Ping Atom = 0xe704 - Placeholder Atom = 0xfb0b - Plaintext Atom = 0x19e09 - Playsinline Atom = 0x10a0b - Poster Atom = 0x2b706 - Pre Atom = 0x46403 - Preload Atom = 0x47a07 - Progress Atom = 0x5ad08 - Prompt Atom = 0x52a06 - Public Atom = 0x57a06 - Q Atom = 0x7701 + Pattern Atom = 0x6607 + Picture Atom = 0x7b07 + Ping Atom = 0xef04 + Placeholder Atom = 0x1310b + Plaintext Atom = 0x1b209 + Playsinline Atom = 0x1400b + Poster Atom = 0x2cf06 + Pre Atom = 0x47003 + Preload Atom = 0x48607 + Progress Atom = 0x5b908 + Prompt Atom = 0x53606 + Public Atom = 0x58606 + Q Atom = 0xcf01 Radiogroup Atom = 0x30a - Readonly Atom = 0x34b08 - Referrerpolicy Atom = 0x3c50e - Rel Atom = 0x47b03 - Required Atom = 0x23408 - Reversed Atom = 0x9c08 - Rows Atom = 0x3a04 - Rowspan Atom = 0x3a07 - Rp Atom = 0x22402 - Rt Atom = 0x17b02 - Ruby Atom = 0xac04 + Rb Atom = 0x3a02 + Readonly Atom = 0x35708 + Referrerpolicy Atom = 0x3d10e + Rel Atom = 0x48703 + Required Atom = 0x24c08 + Reversed Atom = 0x8008 + Rows Atom = 0x9c04 + Rowspan Atom = 0x9c07 + Rp Atom = 0x23c02 + Rt Atom = 0x19a02 + Rtc Atom = 0x19a03 + Ruby Atom = 0xfb04 S Atom = 0x2501 - Samp Atom = 0x4c04 - Sandbox Atom = 0xf307 - Scope Atom = 0x67105 - Scoped Atom = 0x67106 - Script Atom = 0x20006 - Seamless Atom = 0x36508 - Section Atom = 0x5bd07 - Select Atom = 0x63806 - Selected Atom = 0x63808 - Shape Atom = 0x1d505 - Size Atom = 0x5f104 - Sizes Atom = 0x5f105 - Slot Atom = 0x1df04 - Small Atom = 0x1ee05 - Sortable Atom = 0x64d08 - Sorted Atom = 0x32b06 - Source Atom = 0x36c06 - Spacer Atom = 0x42b06 - Span Atom = 0x3d04 - Spellcheck Atom = 0x4680a - Src Atom = 0x5b403 - Srcdoc Atom = 0x5b406 - Srclang Atom = 0x5f507 - Srcset Atom = 0x6f306 - Start Atom = 0x3ee05 - Step Atom = 0x57704 - Strike Atom = 0x7a06 - Strong Atom = 0x31506 - Style Atom = 0x6f905 - Sub Atom = 0x66903 - Summary Atom = 0x6fe07 - Sup Atom = 0x70503 - Svg Atom = 0x70803 - System Atom = 0x70b06 - Tabindex Atom = 0x4b208 - Table Atom = 0x58905 - Target Atom = 0x2ac06 + Samp Atom = 0x7804 + Sandbox Atom = 0x12907 + Scope Atom = 0x67505 + Scoped Atom = 0x67506 + Script Atom = 0x21806 + Seamless Atom = 0x37108 + Section Atom = 0x56807 + Select Atom = 0x63c06 + Selected Atom = 0x63c08 + Shape Atom = 0x1e505 + Size Atom = 0x5f504 + Sizes Atom = 0x5f505 + Slot Atom = 0x1ef04 + Small Atom = 0x20605 + Sortable Atom = 0x65108 + Sorted Atom = 0x33706 + Source Atom = 0x37806 + Spacer Atom = 0x43706 + Span Atom = 0x9f04 + Spellcheck Atom = 0x4740a + Src Atom = 0x5c003 + Srcdoc Atom = 0x5c006 + Srclang Atom = 0x5f907 + Srcset Atom = 0x6f906 + Start Atom = 0x3fa05 + Step Atom = 0x58304 + Strike Atom = 0xd206 + Strong Atom = 0x6dd06 + Style Atom = 0x6ff05 + Sub Atom = 0x66d03 + Summary Atom = 0x70407 + Sup Atom = 0x70b03 + Svg Atom = 0x70e03 + System Atom = 0x71106 + Tabindex Atom = 0x4be08 + Table Atom = 0x59505 + Target Atom = 0x2c406 Tbody Atom = 0x2705 - Td Atom = 0x5e02 - Template Atom = 0x70e08 - Textarea Atom = 0x34608 - Tfoot Atom = 0xb205 - Th Atom = 0x13f02 - Thead Atom = 0x32405 - Time Atom = 0x11c04 - Title Atom = 0xca05 - Tr Atom = 0x7402 - Track Atom = 0x17c05 - Translate Atom = 0x1a609 - Tt Atom = 0x5102 - Type Atom = 0x8104 - Typemustmatch Atom = 0x2780d + Td Atom = 0x9202 + Template Atom = 0x71408 + Textarea Atom = 0x35208 + Tfoot Atom = 0xf505 + Th Atom = 0x15602 + Thead Atom = 0x33005 + Time Atom = 0x4204 + Title Atom = 0x11005 + Tr Atom = 0xcc02 + Track Atom = 0x1ba05 + Translate Atom = 0x1f209 + Tt Atom = 0x6802 + Type Atom = 0xd904 + Typemustmatch Atom = 0x2900d U Atom = 0xb01 - Ul Atom = 0x6602 - Updateviacache Atom = 0x1200e - Usemap Atom = 0x59206 + Ul Atom = 0xa702 + Updateviacache Atom = 0x460e + Usemap Atom = 0x59e06 Value Atom = 0x1505 - Var Atom = 0x15603 - Video Atom = 0x2d905 - Wbr Atom = 0x57003 - Width Atom = 0x64505 - Workertype Atom = 0x7160a - Wrap Atom = 0x72004 - Xmp Atom = 0xf903 + Var Atom = 0x16d03 + Video Atom = 0x2f105 + Wbr Atom = 0x57c03 + Width Atom = 0x64905 + Workertype Atom = 0x71c0a + Wrap Atom = 0x72604 + Xmp Atom = 0x12f03 ) const hash0 = 0x81cdf10e @@ -377,401 +380,404 @@ const maxAtomLen = 25 var table = [1 << 9]Atom{ - 0x1: 0x8e0a, // mediagroup - 0x2: 0x2cc04, // lang + 0x1: 0xe60a, // mediagroup + 0x2: 0x2e404, // lang 0x4: 0x2c09, // accesskey - 0x5: 0x5708, // frameset - 0x7: 0x63608, // onselect - 0x8: 0x70b06, // system - 0xa: 0x64505, // width - 0xc: 0x2710b, // formenctype - 0xd: 0x10102, // ol - 0xe: 0x38b0b, // oncuechange - 0x10: 0x13403, // bdo - 0x11: 0xcf05, // audio - 0x12: 0x18309, // draggable - 0x14: 0x2d905, // video - 0x15: 0x29902, // mn - 0x16: 0x37b04, // menu - 0x17: 0x2b706, // poster - 0x19: 0xb306, // footer - 0x1a: 0x29006, // method - 0x1b: 0x2a008, // datetime - 0x1c: 0x17607, // onabort - 0x1d: 0x1200e, // updateviacache - 0x1e: 0xb905, // async - 0x1f: 0x49106, // onload - 0x21: 0xd308, // oncancel - 0x22: 0x62508, // onseeked - 0x23: 0x2ea05, // image - 0x24: 0x5d412, // onrejectionhandled - 0x26: 0x15d04, // link - 0x27: 0x51106, // output - 0x28: 0x32504, // head - 0x29: 0x4f30c, // onmouseleave - 0x2a: 0x57307, // onpaste - 0x2b: 0x59809, // onplaying - 0x2c: 0x1b407, // colspan - 0x2f: 0x1af05, // color - 0x30: 0x5f104, // size - 0x31: 0x2d00a, // http-equiv + 0x5: 0x8b08, // frameset + 0x7: 0x63a08, // onselect + 0x8: 0x71106, // system + 0xa: 0x64905, // width + 0xc: 0x2890b, // formenctype + 0xd: 0x13702, // ol + 0xe: 0x3970b, // oncuechange + 0x10: 0x14b03, // bdo + 0x11: 0x11505, // audio + 0x12: 0x17a09, // draggable + 0x14: 0x2f105, // video + 0x15: 0x2b102, // mn + 0x16: 0x38704, // menu + 0x17: 0x2cf06, // poster + 0x19: 0xf606, // footer + 0x1a: 0x2a806, // method + 0x1b: 0x2b808, // datetime + 0x1c: 0x19507, // onabort + 0x1d: 0x460e, // updateviacache + 0x1e: 0xff05, // async + 0x1f: 0x49d06, // onload + 0x21: 0x11908, // oncancel + 0x22: 0x62908, // onseeked + 0x23: 0x30205, // image + 0x24: 0x5d812, // onrejectionhandled + 0x26: 0x17404, // link + 0x27: 0x51d06, // output + 0x28: 0x33104, // head + 0x29: 0x4ff0c, // onmouseleave + 0x2a: 0x57f07, // onpaste + 0x2b: 0x5a409, // onplaying + 0x2c: 0x1c407, // colspan + 0x2f: 0x1bf05, // color + 0x30: 0x5f504, // size + 0x31: 0x2e80a, // http-equiv 0x33: 0x601, // i - 0x34: 0x54d0a, // onpagehide - 0x35: 0x68814, // onunhandledrejection - 0x37: 0x41e07, // onerror - 0x3a: 0x11508, // basefont + 0x34: 0x5590a, // onpagehide + 0x35: 0x68c14, // onunhandledrejection + 0x37: 0x42a07, // onerror + 0x3a: 0x3b08, // basefont 0x3f: 0x1303, // nav - 0x40: 0x18004, // kind - 0x41: 0x34b08, // readonly - 0x42: 0x2f006, // mglyph - 0x44: 0x11102, // li - 0x46: 0x2bd06, // hidden - 0x47: 0x70803, // svg - 0x48: 0x57704, // step - 0x49: 0x22709, // integrity - 0x4a: 0x57a06, // public - 0x4c: 0x19703, // col - 0x4d: 0x1680a, // blockquote - 0x4e: 0x34302, // h5 - 0x50: 0x5ad08, // progress - 0x51: 0x5f105, // sizes - 0x52: 0x33902, // h4 - 0x56: 0x32405, // thead - 0x57: 0x7e07, // keytype - 0x58: 0x5ab0a, // onprogress - 0x59: 0x43f09, // inputmode - 0x5a: 0x3a509, // ondragend - 0x5d: 0x39605, // oncut - 0x5e: 0x42b06, // spacer - 0x5f: 0x19708, // colgroup - 0x62: 0x14e02, // is - 0x65: 0xb902, // as - 0x66: 0x53c09, // onoffline - 0x67: 0x32b06, // sorted - 0x69: 0x48110, // onlanguagechange - 0x6c: 0x4310c, // onhashchange - 0x6d: 0xa604, // name - 0x6e: 0xb205, // tfoot - 0x6f: 0x55504, // desc - 0x70: 0x33103, // max - 0x72: 0x1da06, // coords - 0x73: 0x2f502, // h3 - 0x74: 0x6e10e, // onbeforeunload - 0x75: 0x3a04, // rows - 0x76: 0x63806, // select - 0x77: 0xa805, // meter - 0x78: 0x37f06, // itemid - 0x79: 0x5300c, // onmousewheel - 0x7a: 0x5b406, // srcdoc - 0x7d: 0x17c05, // track - 0x7f: 0x30708, // itemtype - 0x82: 0x6302, // mo - 0x83: 0x40f08, // onchange - 0x84: 0x32507, // headers - 0x85: 0x5c80c, // onratechange - 0x86: 0x60419, // onsecuritypolicyviolation - 0x88: 0x49908, // datalist - 0x89: 0x4dc0b, // onmousedown - 0x8a: 0x1df04, // slot - 0x8b: 0x4a410, // onloadedmetadata + 0x40: 0x17704, // kind + 0x41: 0x35708, // readonly + 0x42: 0x30806, // mglyph + 0x44: 0xb202, // li + 0x46: 0x2d506, // hidden + 0x47: 0x70e03, // svg + 0x48: 0x58304, // step + 0x49: 0x23f09, // integrity + 0x4a: 0x58606, // public + 0x4c: 0x1ab03, // col + 0x4d: 0x1870a, // blockquote + 0x4e: 0x34f02, // h5 + 0x50: 0x5b908, // progress + 0x51: 0x5f505, // sizes + 0x52: 0x34502, // h4 + 0x56: 0x33005, // thead + 0x57: 0xd607, // keytype + 0x58: 0x5b70a, // onprogress + 0x59: 0x44b09, // inputmode + 0x5a: 0x3b109, // ondragend + 0x5d: 0x3a205, // oncut + 0x5e: 0x43706, // spacer + 0x5f: 0x1ab08, // colgroup + 0x62: 0x16502, // is + 0x65: 0x3c02, // as + 0x66: 0x54809, // onoffline + 0x67: 0x33706, // sorted + 0x69: 0x48d10, // onlanguagechange + 0x6c: 0x43d0c, // onhashchange + 0x6d: 0x9604, // name + 0x6e: 0xf505, // tfoot + 0x6f: 0x56104, // desc + 0x70: 0x33d03, // max + 0x72: 0x1ea06, // coords + 0x73: 0x30d02, // h3 + 0x74: 0x6e70e, // onbeforeunload + 0x75: 0x9c04, // rows + 0x76: 0x63c06, // select + 0x77: 0x9805, // meter + 0x78: 0x38b06, // itemid + 0x79: 0x53c0c, // onmousewheel + 0x7a: 0x5c006, // srcdoc + 0x7d: 0x1ba05, // track + 0x7f: 0x31f08, // itemtype + 0x82: 0xa402, // mo + 0x83: 0x41b08, // onchange + 0x84: 0x33107, // headers + 0x85: 0x5cc0c, // onratechange + 0x86: 0x60819, // onsecuritypolicyviolation + 0x88: 0x4a508, // datalist + 0x89: 0x4e80b, // onmousedown + 0x8a: 0x1ef04, // slot + 0x8b: 0x4b010, // onloadedmetadata 0x8c: 0x1a06, // accept - 0x8d: 0x25006, // object - 0x91: 0x6af0e, // onvolumechange + 0x8d: 0x26806, // object + 0x91: 0x6b30e, // onvolumechange 0x92: 0x2107, // charset - 0x93: 0x25e13, // onautocompleteerror - 0x94: 0x6913, // allowpaymentrequest + 0x93: 0x27613, // onautocompleteerror + 0x94: 0xc113, // allowpaymentrequest 0x95: 0x2804, // body - 0x96: 0xc407, // default - 0x97: 0x63808, // selected - 0x98: 0x20604, // face - 0x99: 0x1d505, // shape - 0x9b: 0x68008, // ontoggle - 0x9e: 0x64702, // dt - 0x9f: 0x6d904, // mark + 0x96: 0x10a07, // default + 0x97: 0x63c08, // selected + 0x98: 0x21e04, // face + 0x99: 0x1e505, // shape + 0x9b: 0x68408, // ontoggle + 0x9e: 0x64b02, // dt + 0x9f: 0xb604, // mark 0xa1: 0xb01, // u - 0xa4: 0x6a708, // onunload - 0xa5: 0xde04, // loop - 0xa6: 0x14d08, // disabled - 0xaa: 0x41707, // onended - 0xab: 0x6d30a, // malignmark - 0xad: 0x67709, // onsuspend - 0xae: 0x34505, // mtext - 0xaf: 0x64b06, // onsort - 0xb0: 0x55908, // itemprop - 0xb3: 0x66d09, // itemscope - 0xb4: 0x15c05, // blink - 0xb6: 0x3a506, // ondrag - 0xb7: 0x6602, // ul - 0xb8: 0x25604, // form - 0xb9: 0xf307, // sandbox - 0xba: 0x5705, // frame + 0xa4: 0x6ab08, // onunload + 0xa5: 0x5d04, // loop + 0xa6: 0x16408, // disabled + 0xaa: 0x42307, // onended + 0xab: 0xb00a, // malignmark + 0xad: 0x67b09, // onsuspend + 0xae: 0x35105, // mtext + 0xaf: 0x64f06, // onsort + 0xb0: 0x19d08, // itemprop + 0xb3: 0x67109, // itemscope + 0xb4: 0x17305, // blink + 0xb6: 0x3b106, // ondrag + 0xb7: 0xa702, // ul + 0xb8: 0x26e04, // form + 0xb9: 0x12907, // sandbox + 0xba: 0x8b05, // frame 0xbb: 0x1505, // value - 0xbc: 0x65e09, // onstorage - 0xc0: 0x17b02, // rt + 0xbc: 0x66209, // onstorage + 0xbf: 0xaa07, // acronym + 0xc0: 0x19a02, // rt 0xc2: 0x202, // br - 0xc3: 0x20e08, // fieldset - 0xc4: 0x2780d, // typemustmatch - 0xc5: 0x6108, // nomodule - 0xc6: 0x4007, // noembed - 0xc7: 0x69a0d, // onbeforeprint - 0xc8: 0x17206, // button - 0xc9: 0x2dd07, // onclick - 0xca: 0x6fe07, // summary - 0xcd: 0xac04, // ruby - 0xce: 0x5b905, // class - 0xcf: 0x3e80b, // ondragstart - 0xd0: 0x21907, // caption - 0xd4: 0x850e, // allowusermedia - 0xd5: 0x4c30b, // onloadstart - 0xd9: 0x15403, // div - 0xda: 0x49d04, // list - 0xdb: 0x32204, // math - 0xdc: 0x43f05, // input - 0xdf: 0x3de0a, // ondragover - 0xe0: 0x2c602, // h2 - 0xe2: 0x19e09, // plaintext - 0xe4: 0x4e70c, // onmouseenter - 0xe7: 0x46d07, // checked - 0xe8: 0x46403, // pre - 0xea: 0x35308, // multiple - 0xeb: 0x16103, // bdi - 0xec: 0x33109, // maxlength - 0xed: 0x7701, // q - 0xee: 0x61b0a, // onauxclick - 0xf0: 0x57003, // wbr - 0xf2: 0x11504, // base - 0xf3: 0x6dd06, // option - 0xf5: 0x40710, // ondurationchange - 0xf7: 0x5508, // noframes - 0xf9: 0x3f908, // dropzone - 0xfb: 0x67105, // scope - 0xfc: 0x9c08, // reversed - 0xfd: 0x3ae0b, // ondragenter - 0xfe: 0x3ee05, // start - 0xff: 0xf903, // xmp - 0x100: 0x5f507, // srclang - 0x101: 0x2ef03, // img + 0xc3: 0x22608, // fieldset + 0xc4: 0x2900d, // typemustmatch + 0xc5: 0xa208, // nomodule + 0xc6: 0x6c07, // noembed + 0xc7: 0x69e0d, // onbeforeprint + 0xc8: 0x19106, // button + 0xc9: 0x2f507, // onclick + 0xca: 0x70407, // summary + 0xcd: 0xfb04, // ruby + 0xce: 0x56405, // class + 0xcf: 0x3f40b, // ondragstart + 0xd0: 0x23107, // caption + 0xd4: 0xdd0e, // allowusermedia + 0xd5: 0x4cf0b, // onloadstart + 0xd9: 0x16b03, // div + 0xda: 0x4a904, // list + 0xdb: 0x32e04, // math + 0xdc: 0x44b05, // input + 0xdf: 0x3ea0a, // ondragover + 0xe0: 0x2de02, // h2 + 0xe2: 0x1b209, // plaintext + 0xe4: 0x4f30c, // onmouseenter + 0xe7: 0x47907, // checked + 0xe8: 0x47003, // pre + 0xea: 0x35f08, // multiple + 0xeb: 0xba03, // bdi + 0xec: 0x33d09, // maxlength + 0xed: 0xcf01, // q + 0xee: 0x61f0a, // onauxclick + 0xf0: 0x57c03, // wbr + 0xf2: 0x3b04, // base + 0xf3: 0x6e306, // option + 0xf5: 0x41310, // ondurationchange + 0xf7: 0x8908, // noframes + 0xf9: 0x40508, // dropzone + 0xfb: 0x67505, // scope + 0xfc: 0x8008, // reversed + 0xfd: 0x3ba0b, // ondragenter + 0xfe: 0x3fa05, // start + 0xff: 0x12f03, // xmp + 0x100: 0x5f907, // srclang + 0x101: 0x30703, // img 0x104: 0x101, // b - 0x105: 0x23c03, // for - 0x106: 0xc105, // aside - 0x107: 0x43d07, // oninput - 0x108: 0x34a04, // area - 0x109: 0x28c0a, // formmethod - 0x10a: 0x72004, // wrap - 0x10c: 0x22402, // rp - 0x10d: 0x45f0a, // onkeypress - 0x10e: 0x5102, // tt - 0x110: 0x33b02, // mi - 0x111: 0x35b05, // muted - 0x112: 0xb003, // alt - 0x113: 0x19004, // code - 0x114: 0x4202, // em - 0x115: 0x3b90a, // ondragexit - 0x117: 0x3d04, // span - 0x119: 0x30f08, // manifest - 0x11a: 0x37b08, // menuitem - 0x11b: 0x57f07, // content - 0x11d: 0x6bd09, // onwaiting - 0x11f: 0x4ba09, // onloadend - 0x121: 0x3720d, // oncontextmenu - 0x123: 0x5c206, // onblur - 0x124: 0x3f007, // article - 0x125: 0xa303, // dir - 0x126: 0xe704, // ping - 0x127: 0x23408, // required - 0x128: 0x44909, // oninvalid - 0x129: 0x6d405, // align - 0x12b: 0x57e04, // icon - 0x12c: 0x64902, // h6 - 0x12d: 0x1b404, // cols - 0x12e: 0x2160a, // figcaption - 0x12f: 0x45209, // onkeydown - 0x130: 0x66708, // onsubmit - 0x131: 0x13609, // oncanplay - 0x132: 0x70503, // sup + 0x105: 0x25403, // for + 0x106: 0x10705, // aside + 0x107: 0x44907, // oninput + 0x108: 0x35604, // area + 0x109: 0x2a40a, // formmethod + 0x10a: 0x72604, // wrap + 0x10c: 0x23c02, // rp + 0x10d: 0x46b0a, // onkeypress + 0x10e: 0x6802, // tt + 0x110: 0x34702, // mi + 0x111: 0x36705, // muted + 0x112: 0xf303, // alt + 0x113: 0x5c504, // code + 0x114: 0x6e02, // em + 0x115: 0x3c50a, // ondragexit + 0x117: 0x9f04, // span + 0x119: 0x6d708, // manifest + 0x11a: 0x38708, // menuitem + 0x11b: 0x58b07, // content + 0x11d: 0x6c109, // onwaiting + 0x11f: 0x4c609, // onloadend + 0x121: 0x37e0d, // oncontextmenu + 0x123: 0x56d06, // onblur + 0x124: 0x3fc07, // article + 0x125: 0x9303, // dir + 0x126: 0xef04, // ping + 0x127: 0x24c08, // required + 0x128: 0x45509, // oninvalid + 0x129: 0xb105, // align + 0x12b: 0x58a04, // icon + 0x12c: 0x64d02, // h6 + 0x12d: 0x1c404, // cols + 0x12e: 0x22e0a, // figcaption + 0x12f: 0x45e09, // onkeydown + 0x130: 0x66b08, // onsubmit + 0x131: 0x14d09, // oncanplay + 0x132: 0x70b03, // sup 0x133: 0xc01, // p - 0x135: 0x3fe09, // onemptied - 0x136: 0x38506, // oncopy - 0x137: 0x55804, // cite - 0x138: 0x39b0a, // ondblclick - 0x13a: 0x4ff0b, // onmousemove - 0x13c: 0x66903, // sub - 0x13d: 0x47b03, // rel - 0x13e: 0xe008, // optgroup - 0x142: 0x3a07, // rowspan - 0x143: 0x36c06, // source - 0x144: 0x1fe08, // noscript - 0x145: 0x55f04, // open - 0x146: 0x1ec03, // ins - 0x147: 0x23c0d, // foreignObject - 0x148: 0x5a10a, // onpopstate - 0x14a: 0x27507, // enctype - 0x14b: 0x25e0e, // onautocomplete - 0x14c: 0x34608, // textarea - 0x14e: 0x2600c, // autocomplete - 0x14f: 0x14002, // hr - 0x150: 0x1ce08, // controls - 0x151: 0xc302, // id - 0x153: 0x21e0c, // onafterprint - 0x155: 0x2490d, // foreignobject - 0x156: 0x31b07, // marquee - 0x157: 0x58e07, // onpause - 0x158: 0x5e202, // dl - 0x159: 0x12c06, // height - 0x15a: 0x33b03, // min - 0x15b: 0xa307, // dirname - 0x15c: 0x1a609, // translate - 0x15d: 0x13004, // html - 0x15e: 0x33b09, // minlength - 0x15f: 0x47a07, // preload - 0x160: 0x70e08, // template - 0x161: 0x3d30b, // ondragleave - 0x164: 0x5b403, // src - 0x165: 0x31506, // strong - 0x167: 0x4c04, // samp - 0x168: 0x6ed07, // address - 0x169: 0x54508, // ononline - 0x16b: 0xfb0b, // placeholder - 0x16c: 0x2ac06, // target - 0x16d: 0x1ee05, // small - 0x16e: 0x6c607, // onwheel - 0x16f: 0x1b90a, // annotation - 0x170: 0x4680a, // spellcheck - 0x171: 0x4607, // details - 0x172: 0xbd06, // canvas - 0x173: 0xeb09, // autofocus + 0x135: 0x40a09, // onemptied + 0x136: 0x39106, // oncopy + 0x137: 0x19c04, // cite + 0x138: 0x3a70a, // ondblclick + 0x13a: 0x50b0b, // onmousemove + 0x13c: 0x66d03, // sub + 0x13d: 0x48703, // rel + 0x13e: 0x5f08, // optgroup + 0x142: 0x9c07, // rowspan + 0x143: 0x37806, // source + 0x144: 0x21608, // noscript + 0x145: 0x1a304, // open + 0x146: 0x20403, // ins + 0x147: 0x2540d, // foreignObject + 0x148: 0x5ad0a, // onpopstate + 0x14a: 0x28d07, // enctype + 0x14b: 0x2760e, // onautocomplete + 0x14c: 0x35208, // textarea + 0x14e: 0x2780c, // autocomplete + 0x14f: 0x15702, // hr + 0x150: 0x1de08, // controls + 0x151: 0x10902, // id + 0x153: 0x2360c, // onafterprint + 0x155: 0x2610d, // foreignobject + 0x156: 0x32707, // marquee + 0x157: 0x59a07, // onpause + 0x158: 0x5e602, // dl + 0x159: 0x5206, // height + 0x15a: 0x34703, // min + 0x15b: 0x9307, // dirname + 0x15c: 0x1f209, // translate + 0x15d: 0x5604, // html + 0x15e: 0x34709, // minlength + 0x15f: 0x48607, // preload + 0x160: 0x71408, // template + 0x161: 0x3df0b, // ondragleave + 0x162: 0x3a02, // rb + 0x164: 0x5c003, // src + 0x165: 0x6dd06, // strong + 0x167: 0x7804, // samp + 0x168: 0x6f307, // address + 0x169: 0x55108, // ononline + 0x16b: 0x1310b, // placeholder + 0x16c: 0x2c406, // target + 0x16d: 0x20605, // small + 0x16e: 0x6ca07, // onwheel + 0x16f: 0x1c90a, // annotation + 0x170: 0x4740a, // spellcheck + 0x171: 0x7207, // details + 0x172: 0x10306, // canvas + 0x173: 0x12109, // autofocus 0x174: 0xc05, // param - 0x176: 0x45708, // download - 0x177: 0x44603, // del - 0x178: 0x36007, // onclose - 0x179: 0x16003, // kbd - 0x17a: 0x30106, // applet - 0x17b: 0x2c804, // href - 0x17c: 0x5ed08, // onresize - 0x17e: 0x4910c, // onloadeddata - 0x180: 0x7402, // tr - 0x181: 0x2a80a, // formtarget - 0x182: 0xca05, // title - 0x183: 0x6f905, // style - 0x184: 0x7a06, // strike - 0x185: 0x59206, // usemap - 0x186: 0x2e406, // iframe + 0x176: 0x46308, // download + 0x177: 0x45203, // del + 0x178: 0x36c07, // onclose + 0x179: 0xb903, // kbd + 0x17a: 0x31906, // applet + 0x17b: 0x2e004, // href + 0x17c: 0x5f108, // onresize + 0x17e: 0x49d0c, // onloadeddata + 0x180: 0xcc02, // tr + 0x181: 0x2c00a, // formtarget + 0x182: 0x11005, // title + 0x183: 0x6ff05, // style + 0x184: 0xd206, // strike + 0x185: 0x59e06, // usemap + 0x186: 0x2fc06, // iframe 0x187: 0x1004, // main - 0x189: 0x9707, // picture - 0x18c: 0x2fe05, // ismap - 0x18e: 0x49904, // data - 0x18f: 0xda05, // label - 0x191: 0x3c50e, // referrerpolicy - 0x192: 0x13f02, // th - 0x194: 0x52a06, // prompt - 0x195: 0x5bd07, // section - 0x197: 0x6cd07, // optimum - 0x198: 0x2c304, // high - 0x199: 0x14502, // h1 - 0x19a: 0x65509, // onstalled - 0x19b: 0x15603, // var - 0x19c: 0x11c04, // time - 0x19e: 0x67002, // ms - 0x19f: 0x32506, // header - 0x1a0: 0x4ce09, // onmessage - 0x1a1: 0x56205, // nonce - 0x1a2: 0x2560a, // formaction - 0x1a3: 0x20806, // center + 0x189: 0x7b07, // picture + 0x18c: 0x31605, // ismap + 0x18e: 0x4a504, // data + 0x18f: 0x5905, // label + 0x191: 0x3d10e, // referrerpolicy + 0x192: 0x15602, // th + 0x194: 0x53606, // prompt + 0x195: 0x56807, // section + 0x197: 0x6d107, // optimum + 0x198: 0x2db04, // high + 0x199: 0x15c02, // h1 + 0x19a: 0x65909, // onstalled + 0x19b: 0x16d03, // var + 0x19c: 0x4204, // time + 0x19e: 0x67402, // ms + 0x19f: 0x33106, // header + 0x1a0: 0x4da09, // onmessage + 0x1a1: 0x1a605, // nonce + 0x1a2: 0x26e0a, // formaction + 0x1a3: 0x22006, // center 0x1a4: 0x3704, // nobr - 0x1a5: 0x58905, // table - 0x1a6: 0x49d07, // listing - 0x1a7: 0x18a06, // legend - 0x1a9: 0x28309, // challenge - 0x1aa: 0x23006, // figure - 0x1ab: 0x8e05, // media - 0x1ae: 0x8104, // type - 0x1af: 0x11904, // font - 0x1b0: 0x4ce0e, // onmessageerror - 0x1b1: 0x36508, // seamless - 0x1b2: 0x5f03, // dfn - 0x1b3: 0x19205, // defer - 0x1b4: 0x6b03, // low - 0x1b5: 0x62d09, // onseeking - 0x1b6: 0x5170b, // onmouseover - 0x1b7: 0x29a0a, // novalidate - 0x1b8: 0x7160a, // workertype - 0x1ba: 0x3c107, // itemref + 0x1a5: 0x59505, // table + 0x1a6: 0x4a907, // listing + 0x1a7: 0x18106, // legend + 0x1a9: 0x29b09, // challenge + 0x1aa: 0x24806, // figure + 0x1ab: 0xe605, // media + 0x1ae: 0xd904, // type + 0x1af: 0x3f04, // font + 0x1b0: 0x4da0e, // onmessageerror + 0x1b1: 0x37108, // seamless + 0x1b2: 0x8703, // dfn + 0x1b3: 0x5c705, // defer + 0x1b4: 0xc303, // low + 0x1b5: 0x19a03, // rtc + 0x1b6: 0x5230b, // onmouseover + 0x1b7: 0x2b20a, // novalidate + 0x1b8: 0x71c0a, // workertype + 0x1ba: 0x3cd07, // itemref 0x1bd: 0x1, // a - 0x1be: 0x30003, // map - 0x1bf: 0x11a0c, // ontimeupdate - 0x1c0: 0x14707, // bgsound + 0x1be: 0x31803, // map + 0x1bf: 0x400c, // ontimeupdate + 0x1c0: 0x15e07, // bgsound 0x1c1: 0x3206, // keygen 0x1c2: 0x2705, // tbody - 0x1c5: 0x64006, // onshow + 0x1c5: 0x64406, // onshow 0x1c7: 0x2501, // s - 0x1c8: 0x4f07, // pattern - 0x1cc: 0x13610, // oncanplaythrough - 0x1ce: 0x2bf02, // dd - 0x1cf: 0x6f306, // srcset - 0x1d0: 0x15903, // big - 0x1d2: 0x64d08, // sortable - 0x1d3: 0x47407, // onkeyup - 0x1d5: 0x59806, // onplay - 0x1d7: 0x4ac04, // meta - 0x1d8: 0x3f706, // ondrop - 0x1da: 0x5fc08, // onscroll - 0x1db: 0x1e30b, // crossorigin - 0x1dc: 0x5670a, // onpageshow + 0x1c8: 0x6607, // pattern + 0x1cc: 0x14d10, // oncanplaythrough + 0x1ce: 0x2d702, // dd + 0x1cf: 0x6f906, // srcset + 0x1d0: 0x17003, // big + 0x1d2: 0x65108, // sortable + 0x1d3: 0x48007, // onkeyup + 0x1d5: 0x5a406, // onplay + 0x1d7: 0x4b804, // meta + 0x1d8: 0x40306, // ondrop + 0x1da: 0x60008, // onscroll + 0x1db: 0x1fb0b, // crossorigin + 0x1dc: 0x5730a, // onpageshow 0x1dd: 0x4, // abbr - 0x1de: 0x5e02, // td - 0x1df: 0x57f0f, // contenteditable - 0x1e0: 0x25a06, // action - 0x1e1: 0x10a0b, // playsinline - 0x1e2: 0x42507, // onfocus - 0x1e3: 0x2c808, // hreflang - 0x1e5: 0x50a0a, // onmouseout - 0x1e6: 0x5e607, // onreset - 0x1e7: 0x10608, // autoplay - 0x1ea: 0x67106, // scoped + 0x1de: 0x9202, // td + 0x1df: 0x58b0f, // contenteditable + 0x1e0: 0x27206, // action + 0x1e1: 0x1400b, // playsinline + 0x1e2: 0x43107, // onfocus + 0x1e3: 0x2e008, // hreflang + 0x1e5: 0x5160a, // onmouseout + 0x1e6: 0x5ea07, // onreset + 0x1e7: 0x13c08, // autoplay + 0x1e8: 0x63109, // onseeking + 0x1ea: 0x67506, // scoped 0x1ec: 0x30a, // radiogroup - 0x1ee: 0x3740b, // contextmenu - 0x1ef: 0x52209, // onmouseup - 0x1f1: 0x2b206, // hgroup - 0x1f2: 0x1f00f, // allowfullscreen - 0x1f3: 0x4b208, // tabindex - 0x1f6: 0x2f707, // isindex + 0x1ee: 0x3800b, // contextmenu + 0x1ef: 0x52e09, // onmouseup + 0x1f1: 0x2ca06, // hgroup + 0x1f2: 0x2080f, // allowfullscreen + 0x1f3: 0x4be08, // tabindex + 0x1f6: 0x30f07, // isindex 0x1f7: 0x1a0e, // accept-charset - 0x1f8: 0x2960e, // formnovalidate - 0x1fb: 0x1b90e, // annotation-xml - 0x1fc: 0x4205, // embed - 0x1fd: 0x20006, // script - 0x1fe: 0x16206, // dialog - 0x1ff: 0x1c707, // command + 0x1f8: 0x2ae0e, // formnovalidate + 0x1fb: 0x1c90e, // annotation-xml + 0x1fc: 0x6e05, // embed + 0x1fd: 0x21806, // script + 0x1fe: 0xbb06, // dialog + 0x1ff: 0x1d707, // command } -const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobro" + - "wspanoembedetailsampatternoframesetdfnomoduleallowpaymentreq" + - "uestrikeytypeallowusermediagroupictureversedirnameterubyaltf" + - "ooterasyncanvasidefaultitleaudioncancelabelooptgroupingautof" + - "ocusandboxmplaceholderautoplaysinlinebasefontimeupdateviacac" + - "heightmlbdoncanplaythrough1bgsoundisabledivarbigblinkbdialog" + - "blockquotebuttonabortrackindraggablegendcodefercolgrouplaint" + - "extranslatecolorcolspannotation-xmlcommandcontrolshapecoords" + - "lotcrossoriginsmallowfullscreenoscriptfacenterfieldsetfigcap" + - "tionafterprintegrityfigurequiredforeignObjectforeignobjectfo" + - "rmactionautocompleteerrorformenctypemustmatchallengeformmeth" + - "odformnovalidatetimeformtargethgrouposterhiddenhigh2hreflang" + - "http-equivideonclickiframeimageimglyph3isindexismappletitemt" + - "ypemanifestrongmarqueematheadersortedmaxlength4minlength5mte" + - "xtareadonlymultiplemutedoncloseamlessourceoncontextmenuitemi" + - "doncopyoncuechangeoncutondblclickondragendondragenterondrage" + - "xitemreferrerpolicyondragleaveondragoverondragstarticleondro" + - "pzonemptiedondurationchangeonendedonerroronfocuspaceronhashc" + - "hangeoninputmodeloninvalidonkeydownloadonkeypresspellchecked" + - "onkeyupreloadonlanguagechangeonloadeddatalistingonloadedmeta" + - "databindexonloadendonloadstartonmessageerroronmousedownonmou" + - "seenteronmouseleaveonmousemoveonmouseoutputonmouseoveronmous" + - "eupromptonmousewheelonofflineononlineonpagehidescitempropeno" + - "nceonpageshowbronpastepublicontenteditableonpausemaponplayin" + - "gonpopstateonprogressrcdoclassectionbluronratechangeonreject" + - "ionhandledonresetonresizesrclangonscrollonsecuritypolicyviol" + - "ationauxclickonseekedonseekingonselectedonshowidth6onsortabl" + - "eonstalledonstorageonsubmitemscopedonsuspendontoggleonunhand" + - "ledrejectionbeforeprintonunloadonvolumechangeonwaitingonwhee" + - "loptimumalignmarkoptionbeforeunloaddressrcsetstylesummarysup" + - "svgsystemplateworkertypewrap" +const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobrb" + + "asefontimeupdateviacacheightmlabelooptgroupatternoembedetail" + + "sampictureversedfnoframesetdirnameterowspanomoduleacronymali" + + "gnmarkbdialogallowpaymentrequestrikeytypeallowusermediagroup" + + "ingaltfooterubyasyncanvasidefaultitleaudioncancelautofocusan" + + "dboxmplaceholderautoplaysinlinebdoncanplaythrough1bgsoundisa" + + "bledivarbigblinkindraggablegendblockquotebuttonabortcitempro" + + "penoncecolgrouplaintextrackcolorcolspannotation-xmlcommandco" + + "ntrolshapecoordslotranslatecrossoriginsmallowfullscreenoscri" + + "ptfacenterfieldsetfigcaptionafterprintegrityfigurequiredfore" + + "ignObjectforeignobjectformactionautocompleteerrorformenctype" + + "mustmatchallengeformmethodformnovalidatetimeformtargethgroup" + + "osterhiddenhigh2hreflanghttp-equivideonclickiframeimageimgly" + + "ph3isindexismappletitemtypemarqueematheadersortedmaxlength4m" + + "inlength5mtextareadonlymultiplemutedoncloseamlessourceoncont" + + "extmenuitemidoncopyoncuechangeoncutondblclickondragendondrag" + + "enterondragexitemreferrerpolicyondragleaveondragoverondragst" + + "articleondropzonemptiedondurationchangeonendedonerroronfocus" + + "paceronhashchangeoninputmodeloninvalidonkeydownloadonkeypres" + + "spellcheckedonkeyupreloadonlanguagechangeonloadeddatalisting" + + "onloadedmetadatabindexonloadendonloadstartonmessageerroronmo" + + "usedownonmouseenteronmouseleaveonmousemoveonmouseoutputonmou" + + "seoveronmouseupromptonmousewheelonofflineononlineonpagehides" + + "classectionbluronpageshowbronpastepublicontenteditableonpaus" + + "emaponplayingonpopstateonprogressrcdocodeferonratechangeonre" + + "jectionhandledonresetonresizesrclangonscrollonsecuritypolicy" + + "violationauxclickonseekedonseekingonselectedonshowidth6onsor" + + "tableonstalledonstorageonsubmitemscopedonsuspendontoggleonun" + + "handledrejectionbeforeprintonunloadonvolumechangeonwaitingon" + + "wheeloptimumanifestrongoptionbeforeunloaddressrcsetstylesumm" + + "arysupsvgsystemplateworkertypewrap" diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/atom/table_test.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/atom/table_test.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/atom/table_test.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/atom/table_test.go 2019-08-17 11:56:26.000000000 +0000 @@ -10,6 +10,7 @@ "accept", "accept-charset", "accesskey", + "acronym", "action", "address", "align", @@ -295,6 +296,7 @@ "public", "q", "radiogroup", + "rb", "readonly", "referrerpolicy", "rel", @@ -304,6 +306,7 @@ "rowspan", "rp", "rt", + "rtc", "ruby", "s", "samp", diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/const.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/const.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/const.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/const.go 2019-08-17 11:56:26.000000000 +0000 @@ -4,7 +4,7 @@ package html -// Section 12.2.3.2 of the HTML5 specification says "The following elements +// Section 12.2.4.2 of the HTML5 specification says "The following elements // have varying levels of special parsing rules". // https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements var isSpecialElementMap = map[string]bool{ @@ -97,8 +97,16 @@ switch element.Namespace { case "", "html": return isSpecialElementMap[element.Data] + case "math": + switch element.Data { + case "mi", "mo", "mn", "ms", "mtext", "annotation-xml": + return true + } case "svg": - return element.Data == "foreignObject" + switch element.Data { + case "foreignObject", "desc", "title": + return true + } } return false } diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/entity.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/entity.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/entity.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/entity.go 2019-08-17 11:56:26.000000000 +0000 @@ -75,2083 +75,2083 @@ "Copf;": '\U00002102', "Coproduct;": '\U00002210', "CounterClockwiseContourIntegral;": '\U00002233', - "Cross;": '\U00002A2F', - "Cscr;": '\U0001D49E', - "Cup;": '\U000022D3', - "CupCap;": '\U0000224D', - "DD;": '\U00002145', - "DDotrahd;": '\U00002911', - "DJcy;": '\U00000402', - "DScy;": '\U00000405', - "DZcy;": '\U0000040F', - "Dagger;": '\U00002021', - "Darr;": '\U000021A1', - "Dashv;": '\U00002AE4', - "Dcaron;": '\U0000010E', - "Dcy;": '\U00000414', - "Del;": '\U00002207', - "Delta;": '\U00000394', - "Dfr;": '\U0001D507', - "DiacriticalAcute;": '\U000000B4', - "DiacriticalDot;": '\U000002D9', - "DiacriticalDoubleAcute;": '\U000002DD', - "DiacriticalGrave;": '\U00000060', - "DiacriticalTilde;": '\U000002DC', - "Diamond;": '\U000022C4', - "DifferentialD;": '\U00002146', - "Dopf;": '\U0001D53B', - "Dot;": '\U000000A8', - "DotDot;": '\U000020DC', - "DotEqual;": '\U00002250', - "DoubleContourIntegral;": '\U0000222F', - "DoubleDot;": '\U000000A8', - "DoubleDownArrow;": '\U000021D3', - "DoubleLeftArrow;": '\U000021D0', - "DoubleLeftRightArrow;": '\U000021D4', - "DoubleLeftTee;": '\U00002AE4', - "DoubleLongLeftArrow;": '\U000027F8', - "DoubleLongLeftRightArrow;": '\U000027FA', - "DoubleLongRightArrow;": '\U000027F9', - "DoubleRightArrow;": '\U000021D2', - "DoubleRightTee;": '\U000022A8', - "DoubleUpArrow;": '\U000021D1', - "DoubleUpDownArrow;": '\U000021D5', - "DoubleVerticalBar;": '\U00002225', - "DownArrow;": '\U00002193', - "DownArrowBar;": '\U00002913', - "DownArrowUpArrow;": '\U000021F5', - "DownBreve;": '\U00000311', - "DownLeftRightVector;": '\U00002950', - "DownLeftTeeVector;": '\U0000295E', - "DownLeftVector;": '\U000021BD', - "DownLeftVectorBar;": '\U00002956', - "DownRightTeeVector;": '\U0000295F', - "DownRightVector;": '\U000021C1', - "DownRightVectorBar;": '\U00002957', - "DownTee;": '\U000022A4', - "DownTeeArrow;": '\U000021A7', - "Downarrow;": '\U000021D3', - "Dscr;": '\U0001D49F', - "Dstrok;": '\U00000110', - "ENG;": '\U0000014A', - "ETH;": '\U000000D0', - "Eacute;": '\U000000C9', - "Ecaron;": '\U0000011A', - "Ecirc;": '\U000000CA', - "Ecy;": '\U0000042D', - "Edot;": '\U00000116', - "Efr;": '\U0001D508', - "Egrave;": '\U000000C8', - "Element;": '\U00002208', - "Emacr;": '\U00000112', - "EmptySmallSquare;": '\U000025FB', - "EmptyVerySmallSquare;": '\U000025AB', - "Eogon;": '\U00000118', - "Eopf;": '\U0001D53C', - "Epsilon;": '\U00000395', - "Equal;": '\U00002A75', - "EqualTilde;": '\U00002242', - "Equilibrium;": '\U000021CC', - "Escr;": '\U00002130', - "Esim;": '\U00002A73', - "Eta;": '\U00000397', - "Euml;": '\U000000CB', - "Exists;": '\U00002203', - "ExponentialE;": '\U00002147', - "Fcy;": '\U00000424', - "Ffr;": '\U0001D509', - "FilledSmallSquare;": '\U000025FC', - "FilledVerySmallSquare;": '\U000025AA', - "Fopf;": '\U0001D53D', - "ForAll;": '\U00002200', - "Fouriertrf;": '\U00002131', - "Fscr;": '\U00002131', - "GJcy;": '\U00000403', - "GT;": '\U0000003E', - "Gamma;": '\U00000393', - "Gammad;": '\U000003DC', - "Gbreve;": '\U0000011E', - "Gcedil;": '\U00000122', - "Gcirc;": '\U0000011C', - "Gcy;": '\U00000413', - "Gdot;": '\U00000120', - "Gfr;": '\U0001D50A', - "Gg;": '\U000022D9', - "Gopf;": '\U0001D53E', - "GreaterEqual;": '\U00002265', - "GreaterEqualLess;": '\U000022DB', - "GreaterFullEqual;": '\U00002267', - "GreaterGreater;": '\U00002AA2', - "GreaterLess;": '\U00002277', - "GreaterSlantEqual;": '\U00002A7E', - "GreaterTilde;": '\U00002273', - "Gscr;": '\U0001D4A2', - "Gt;": '\U0000226B', - "HARDcy;": '\U0000042A', - "Hacek;": '\U000002C7', - "Hat;": '\U0000005E', - "Hcirc;": '\U00000124', - "Hfr;": '\U0000210C', - "HilbertSpace;": '\U0000210B', - "Hopf;": '\U0000210D', - "HorizontalLine;": '\U00002500', - "Hscr;": '\U0000210B', - "Hstrok;": '\U00000126', - "HumpDownHump;": '\U0000224E', - "HumpEqual;": '\U0000224F', - "IEcy;": '\U00000415', - "IJlig;": '\U00000132', - "IOcy;": '\U00000401', - "Iacute;": '\U000000CD', - "Icirc;": '\U000000CE', - "Icy;": '\U00000418', - "Idot;": '\U00000130', - "Ifr;": '\U00002111', - "Igrave;": '\U000000CC', - "Im;": '\U00002111', - "Imacr;": '\U0000012A', - "ImaginaryI;": '\U00002148', - "Implies;": '\U000021D2', - "Int;": '\U0000222C', - "Integral;": '\U0000222B', - "Intersection;": '\U000022C2', - "InvisibleComma;": '\U00002063', - "InvisibleTimes;": '\U00002062', - "Iogon;": '\U0000012E', - "Iopf;": '\U0001D540', - "Iota;": '\U00000399', - "Iscr;": '\U00002110', - "Itilde;": '\U00000128', - "Iukcy;": '\U00000406', - "Iuml;": '\U000000CF', - "Jcirc;": '\U00000134', - "Jcy;": '\U00000419', - "Jfr;": '\U0001D50D', - "Jopf;": '\U0001D541', - "Jscr;": '\U0001D4A5', - "Jsercy;": '\U00000408', - "Jukcy;": '\U00000404', - "KHcy;": '\U00000425', - "KJcy;": '\U0000040C', - "Kappa;": '\U0000039A', - "Kcedil;": '\U00000136', - "Kcy;": '\U0000041A', - "Kfr;": '\U0001D50E', - "Kopf;": '\U0001D542', - "Kscr;": '\U0001D4A6', - "LJcy;": '\U00000409', - "LT;": '\U0000003C', - "Lacute;": '\U00000139', - "Lambda;": '\U0000039B', - "Lang;": '\U000027EA', - "Laplacetrf;": '\U00002112', - "Larr;": '\U0000219E', - "Lcaron;": '\U0000013D', - "Lcedil;": '\U0000013B', - "Lcy;": '\U0000041B', - "LeftAngleBracket;": '\U000027E8', - "LeftArrow;": '\U00002190', - "LeftArrowBar;": '\U000021E4', - "LeftArrowRightArrow;": '\U000021C6', - "LeftCeiling;": '\U00002308', - "LeftDoubleBracket;": '\U000027E6', - "LeftDownTeeVector;": '\U00002961', - "LeftDownVector;": '\U000021C3', - "LeftDownVectorBar;": '\U00002959', - "LeftFloor;": '\U0000230A', - "LeftRightArrow;": '\U00002194', - "LeftRightVector;": '\U0000294E', - "LeftTee;": '\U000022A3', - "LeftTeeArrow;": '\U000021A4', - "LeftTeeVector;": '\U0000295A', - "LeftTriangle;": '\U000022B2', - "LeftTriangleBar;": '\U000029CF', - "LeftTriangleEqual;": '\U000022B4', - "LeftUpDownVector;": '\U00002951', - "LeftUpTeeVector;": '\U00002960', - "LeftUpVector;": '\U000021BF', - "LeftUpVectorBar;": '\U00002958', - "LeftVector;": '\U000021BC', - "LeftVectorBar;": '\U00002952', - "Leftarrow;": '\U000021D0', - "Leftrightarrow;": '\U000021D4', - "LessEqualGreater;": '\U000022DA', - "LessFullEqual;": '\U00002266', - "LessGreater;": '\U00002276', - "LessLess;": '\U00002AA1', - "LessSlantEqual;": '\U00002A7D', - "LessTilde;": '\U00002272', - "Lfr;": '\U0001D50F', - "Ll;": '\U000022D8', - "Lleftarrow;": '\U000021DA', - "Lmidot;": '\U0000013F', - "LongLeftArrow;": '\U000027F5', - "LongLeftRightArrow;": '\U000027F7', - "LongRightArrow;": '\U000027F6', - "Longleftarrow;": '\U000027F8', - "Longleftrightarrow;": '\U000027FA', - "Longrightarrow;": '\U000027F9', - "Lopf;": '\U0001D543', - "LowerLeftArrow;": '\U00002199', - "LowerRightArrow;": '\U00002198', - "Lscr;": '\U00002112', - "Lsh;": '\U000021B0', - "Lstrok;": '\U00000141', - "Lt;": '\U0000226A', - "Map;": '\U00002905', - "Mcy;": '\U0000041C', - "MediumSpace;": '\U0000205F', - "Mellintrf;": '\U00002133', - "Mfr;": '\U0001D510', - "MinusPlus;": '\U00002213', - "Mopf;": '\U0001D544', - "Mscr;": '\U00002133', - "Mu;": '\U0000039C', - "NJcy;": '\U0000040A', - "Nacute;": '\U00000143', - "Ncaron;": '\U00000147', - "Ncedil;": '\U00000145', - "Ncy;": '\U0000041D', - "NegativeMediumSpace;": '\U0000200B', - "NegativeThickSpace;": '\U0000200B', - "NegativeThinSpace;": '\U0000200B', - "NegativeVeryThinSpace;": '\U0000200B', - "NestedGreaterGreater;": '\U0000226B', - "NestedLessLess;": '\U0000226A', - "NewLine;": '\U0000000A', - "Nfr;": '\U0001D511', - "NoBreak;": '\U00002060', - "NonBreakingSpace;": '\U000000A0', - "Nopf;": '\U00002115', - "Not;": '\U00002AEC', - "NotCongruent;": '\U00002262', - "NotCupCap;": '\U0000226D', - "NotDoubleVerticalBar;": '\U00002226', - "NotElement;": '\U00002209', - "NotEqual;": '\U00002260', - "NotExists;": '\U00002204', - "NotGreater;": '\U0000226F', - "NotGreaterEqual;": '\U00002271', - "NotGreaterLess;": '\U00002279', - "NotGreaterTilde;": '\U00002275', - "NotLeftTriangle;": '\U000022EA', - "NotLeftTriangleEqual;": '\U000022EC', - "NotLess;": '\U0000226E', - "NotLessEqual;": '\U00002270', - "NotLessGreater;": '\U00002278', - "NotLessTilde;": '\U00002274', - "NotPrecedes;": '\U00002280', - "NotPrecedesSlantEqual;": '\U000022E0', - "NotReverseElement;": '\U0000220C', - "NotRightTriangle;": '\U000022EB', - "NotRightTriangleEqual;": '\U000022ED', - "NotSquareSubsetEqual;": '\U000022E2', - "NotSquareSupersetEqual;": '\U000022E3', - "NotSubsetEqual;": '\U00002288', - "NotSucceeds;": '\U00002281', - "NotSucceedsSlantEqual;": '\U000022E1', - "NotSupersetEqual;": '\U00002289', - "NotTilde;": '\U00002241', - "NotTildeEqual;": '\U00002244', - "NotTildeFullEqual;": '\U00002247', - "NotTildeTilde;": '\U00002249', - "NotVerticalBar;": '\U00002224', - "Nscr;": '\U0001D4A9', - "Ntilde;": '\U000000D1', - "Nu;": '\U0000039D', - "OElig;": '\U00000152', - "Oacute;": '\U000000D3', - "Ocirc;": '\U000000D4', - "Ocy;": '\U0000041E', - "Odblac;": '\U00000150', - "Ofr;": '\U0001D512', - "Ograve;": '\U000000D2', - "Omacr;": '\U0000014C', - "Omega;": '\U000003A9', - "Omicron;": '\U0000039F', - "Oopf;": '\U0001D546', - "OpenCurlyDoubleQuote;": '\U0000201C', - "OpenCurlyQuote;": '\U00002018', - "Or;": '\U00002A54', - "Oscr;": '\U0001D4AA', - "Oslash;": '\U000000D8', - "Otilde;": '\U000000D5', - "Otimes;": '\U00002A37', - "Ouml;": '\U000000D6', - "OverBar;": '\U0000203E', - "OverBrace;": '\U000023DE', - "OverBracket;": '\U000023B4', - "OverParenthesis;": '\U000023DC', - "PartialD;": '\U00002202', - "Pcy;": '\U0000041F', - "Pfr;": '\U0001D513', - "Phi;": '\U000003A6', - "Pi;": '\U000003A0', - "PlusMinus;": '\U000000B1', - "Poincareplane;": '\U0000210C', - "Popf;": '\U00002119', - "Pr;": '\U00002ABB', - "Precedes;": '\U0000227A', - "PrecedesEqual;": '\U00002AAF', - "PrecedesSlantEqual;": '\U0000227C', - "PrecedesTilde;": '\U0000227E', - "Prime;": '\U00002033', - "Product;": '\U0000220F', - "Proportion;": '\U00002237', - "Proportional;": '\U0000221D', - "Pscr;": '\U0001D4AB', - "Psi;": '\U000003A8', - "QUOT;": '\U00000022', - "Qfr;": '\U0001D514', - "Qopf;": '\U0000211A', - "Qscr;": '\U0001D4AC', - "RBarr;": '\U00002910', - "REG;": '\U000000AE', - "Racute;": '\U00000154', - "Rang;": '\U000027EB', - "Rarr;": '\U000021A0', - "Rarrtl;": '\U00002916', - "Rcaron;": '\U00000158', - "Rcedil;": '\U00000156', - "Rcy;": '\U00000420', - "Re;": '\U0000211C', - "ReverseElement;": '\U0000220B', - "ReverseEquilibrium;": '\U000021CB', - "ReverseUpEquilibrium;": '\U0000296F', - "Rfr;": '\U0000211C', - "Rho;": '\U000003A1', - "RightAngleBracket;": '\U000027E9', - "RightArrow;": '\U00002192', - "RightArrowBar;": '\U000021E5', - "RightArrowLeftArrow;": '\U000021C4', - "RightCeiling;": '\U00002309', - "RightDoubleBracket;": '\U000027E7', - "RightDownTeeVector;": '\U0000295D', - "RightDownVector;": '\U000021C2', - "RightDownVectorBar;": '\U00002955', - "RightFloor;": '\U0000230B', - "RightTee;": '\U000022A2', - "RightTeeArrow;": '\U000021A6', - "RightTeeVector;": '\U0000295B', - "RightTriangle;": '\U000022B3', - "RightTriangleBar;": '\U000029D0', - "RightTriangleEqual;": '\U000022B5', - "RightUpDownVector;": '\U0000294F', - "RightUpTeeVector;": '\U0000295C', - "RightUpVector;": '\U000021BE', - "RightUpVectorBar;": '\U00002954', - "RightVector;": '\U000021C0', - "RightVectorBar;": '\U00002953', - "Rightarrow;": '\U000021D2', - "Ropf;": '\U0000211D', - "RoundImplies;": '\U00002970', - "Rrightarrow;": '\U000021DB', - "Rscr;": '\U0000211B', - "Rsh;": '\U000021B1', - "RuleDelayed;": '\U000029F4', - "SHCHcy;": '\U00000429', - "SHcy;": '\U00000428', - "SOFTcy;": '\U0000042C', - "Sacute;": '\U0000015A', - "Sc;": '\U00002ABC', - "Scaron;": '\U00000160', - "Scedil;": '\U0000015E', - "Scirc;": '\U0000015C', - "Scy;": '\U00000421', - "Sfr;": '\U0001D516', - "ShortDownArrow;": '\U00002193', - "ShortLeftArrow;": '\U00002190', - "ShortRightArrow;": '\U00002192', - "ShortUpArrow;": '\U00002191', - "Sigma;": '\U000003A3', - "SmallCircle;": '\U00002218', - "Sopf;": '\U0001D54A', - "Sqrt;": '\U0000221A', - "Square;": '\U000025A1', - "SquareIntersection;": '\U00002293', - "SquareSubset;": '\U0000228F', - "SquareSubsetEqual;": '\U00002291', - "SquareSuperset;": '\U00002290', - "SquareSupersetEqual;": '\U00002292', - "SquareUnion;": '\U00002294', - "Sscr;": '\U0001D4AE', - "Star;": '\U000022C6', - "Sub;": '\U000022D0', - "Subset;": '\U000022D0', - "SubsetEqual;": '\U00002286', - "Succeeds;": '\U0000227B', - "SucceedsEqual;": '\U00002AB0', - "SucceedsSlantEqual;": '\U0000227D', - "SucceedsTilde;": '\U0000227F', - "SuchThat;": '\U0000220B', - "Sum;": '\U00002211', - "Sup;": '\U000022D1', - "Superset;": '\U00002283', - "SupersetEqual;": '\U00002287', - "Supset;": '\U000022D1', - "THORN;": '\U000000DE', - "TRADE;": '\U00002122', - "TSHcy;": '\U0000040B', - "TScy;": '\U00000426', - "Tab;": '\U00000009', - "Tau;": '\U000003A4', - "Tcaron;": '\U00000164', - "Tcedil;": '\U00000162', - "Tcy;": '\U00000422', - "Tfr;": '\U0001D517', - "Therefore;": '\U00002234', - "Theta;": '\U00000398', - "ThinSpace;": '\U00002009', - "Tilde;": '\U0000223C', - "TildeEqual;": '\U00002243', - "TildeFullEqual;": '\U00002245', - "TildeTilde;": '\U00002248', - "Topf;": '\U0001D54B', - "TripleDot;": '\U000020DB', - "Tscr;": '\U0001D4AF', - "Tstrok;": '\U00000166', - "Uacute;": '\U000000DA', - "Uarr;": '\U0000219F', - "Uarrocir;": '\U00002949', - "Ubrcy;": '\U0000040E', - "Ubreve;": '\U0000016C', - "Ucirc;": '\U000000DB', - "Ucy;": '\U00000423', - "Udblac;": '\U00000170', - "Ufr;": '\U0001D518', - "Ugrave;": '\U000000D9', - "Umacr;": '\U0000016A', - "UnderBar;": '\U0000005F', - "UnderBrace;": '\U000023DF', - "UnderBracket;": '\U000023B5', - "UnderParenthesis;": '\U000023DD', - "Union;": '\U000022C3', - "UnionPlus;": '\U0000228E', - "Uogon;": '\U00000172', - "Uopf;": '\U0001D54C', - "UpArrow;": '\U00002191', - "UpArrowBar;": '\U00002912', - "UpArrowDownArrow;": '\U000021C5', - "UpDownArrow;": '\U00002195', - "UpEquilibrium;": '\U0000296E', - "UpTee;": '\U000022A5', - "UpTeeArrow;": '\U000021A5', - "Uparrow;": '\U000021D1', - "Updownarrow;": '\U000021D5', - "UpperLeftArrow;": '\U00002196', - "UpperRightArrow;": '\U00002197', - "Upsi;": '\U000003D2', - "Upsilon;": '\U000003A5', - "Uring;": '\U0000016E', - "Uscr;": '\U0001D4B0', - "Utilde;": '\U00000168', - "Uuml;": '\U000000DC', - "VDash;": '\U000022AB', - "Vbar;": '\U00002AEB', - "Vcy;": '\U00000412', - "Vdash;": '\U000022A9', - "Vdashl;": '\U00002AE6', - "Vee;": '\U000022C1', - "Verbar;": '\U00002016', - "Vert;": '\U00002016', - "VerticalBar;": '\U00002223', - "VerticalLine;": '\U0000007C', - "VerticalSeparator;": '\U00002758', - "VerticalTilde;": '\U00002240', - "VeryThinSpace;": '\U0000200A', - "Vfr;": '\U0001D519', - "Vopf;": '\U0001D54D', - "Vscr;": '\U0001D4B1', - "Vvdash;": '\U000022AA', - "Wcirc;": '\U00000174', - "Wedge;": '\U000022C0', - "Wfr;": '\U0001D51A', - "Wopf;": '\U0001D54E', - "Wscr;": '\U0001D4B2', - "Xfr;": '\U0001D51B', - "Xi;": '\U0000039E', - "Xopf;": '\U0001D54F', - "Xscr;": '\U0001D4B3', - "YAcy;": '\U0000042F', - "YIcy;": '\U00000407', - "YUcy;": '\U0000042E', - "Yacute;": '\U000000DD', - "Ycirc;": '\U00000176', - "Ycy;": '\U0000042B', - "Yfr;": '\U0001D51C', - "Yopf;": '\U0001D550', - "Yscr;": '\U0001D4B4', - "Yuml;": '\U00000178', - "ZHcy;": '\U00000416', - "Zacute;": '\U00000179', - "Zcaron;": '\U0000017D', - "Zcy;": '\U00000417', - "Zdot;": '\U0000017B', - "ZeroWidthSpace;": '\U0000200B', - "Zeta;": '\U00000396', - "Zfr;": '\U00002128', - "Zopf;": '\U00002124', - "Zscr;": '\U0001D4B5', - "aacute;": '\U000000E1', - "abreve;": '\U00000103', - "ac;": '\U0000223E', - "acd;": '\U0000223F', - "acirc;": '\U000000E2', - "acute;": '\U000000B4', - "acy;": '\U00000430', - "aelig;": '\U000000E6', - "af;": '\U00002061', - "afr;": '\U0001D51E', - "agrave;": '\U000000E0', - "alefsym;": '\U00002135', - "aleph;": '\U00002135', - "alpha;": '\U000003B1', - "amacr;": '\U00000101', - "amalg;": '\U00002A3F', - "amp;": '\U00000026', - "and;": '\U00002227', - "andand;": '\U00002A55', - "andd;": '\U00002A5C', - "andslope;": '\U00002A58', - "andv;": '\U00002A5A', - "ang;": '\U00002220', - "ange;": '\U000029A4', - "angle;": '\U00002220', - "angmsd;": '\U00002221', - "angmsdaa;": '\U000029A8', - "angmsdab;": '\U000029A9', - "angmsdac;": '\U000029AA', - "angmsdad;": '\U000029AB', - "angmsdae;": '\U000029AC', - "angmsdaf;": '\U000029AD', - "angmsdag;": '\U000029AE', - "angmsdah;": '\U000029AF', - "angrt;": '\U0000221F', - "angrtvb;": '\U000022BE', - "angrtvbd;": '\U0000299D', - "angsph;": '\U00002222', - "angst;": '\U000000C5', - "angzarr;": '\U0000237C', - "aogon;": '\U00000105', - "aopf;": '\U0001D552', - "ap;": '\U00002248', - "apE;": '\U00002A70', - "apacir;": '\U00002A6F', - "ape;": '\U0000224A', - "apid;": '\U0000224B', - "apos;": '\U00000027', - "approx;": '\U00002248', - "approxeq;": '\U0000224A', - "aring;": '\U000000E5', - "ascr;": '\U0001D4B6', - "ast;": '\U0000002A', - "asymp;": '\U00002248', - "asympeq;": '\U0000224D', - "atilde;": '\U000000E3', - "auml;": '\U000000E4', - "awconint;": '\U00002233', - "awint;": '\U00002A11', - "bNot;": '\U00002AED', - "backcong;": '\U0000224C', - "backepsilon;": '\U000003F6', - "backprime;": '\U00002035', - "backsim;": '\U0000223D', - "backsimeq;": '\U000022CD', - "barvee;": '\U000022BD', - "barwed;": '\U00002305', - "barwedge;": '\U00002305', - "bbrk;": '\U000023B5', - "bbrktbrk;": '\U000023B6', - "bcong;": '\U0000224C', - "bcy;": '\U00000431', - "bdquo;": '\U0000201E', - "becaus;": '\U00002235', - "because;": '\U00002235', - "bemptyv;": '\U000029B0', - "bepsi;": '\U000003F6', - "bernou;": '\U0000212C', - "beta;": '\U000003B2', - "beth;": '\U00002136', - "between;": '\U0000226C', - "bfr;": '\U0001D51F', - "bigcap;": '\U000022C2', - "bigcirc;": '\U000025EF', - "bigcup;": '\U000022C3', - "bigodot;": '\U00002A00', - "bigoplus;": '\U00002A01', - "bigotimes;": '\U00002A02', - "bigsqcup;": '\U00002A06', - "bigstar;": '\U00002605', - "bigtriangledown;": '\U000025BD', - "bigtriangleup;": '\U000025B3', - "biguplus;": '\U00002A04', - "bigvee;": '\U000022C1', - "bigwedge;": '\U000022C0', - "bkarow;": '\U0000290D', - "blacklozenge;": '\U000029EB', - "blacksquare;": '\U000025AA', - "blacktriangle;": '\U000025B4', - "blacktriangledown;": '\U000025BE', - "blacktriangleleft;": '\U000025C2', - "blacktriangleright;": '\U000025B8', - "blank;": '\U00002423', - "blk12;": '\U00002592', - "blk14;": '\U00002591', - "blk34;": '\U00002593', - "block;": '\U00002588', - "bnot;": '\U00002310', - "bopf;": '\U0001D553', - "bot;": '\U000022A5', - "bottom;": '\U000022A5', - "bowtie;": '\U000022C8', - "boxDL;": '\U00002557', - "boxDR;": '\U00002554', - "boxDl;": '\U00002556', - "boxDr;": '\U00002553', - "boxH;": '\U00002550', - "boxHD;": '\U00002566', - "boxHU;": '\U00002569', - "boxHd;": '\U00002564', - "boxHu;": '\U00002567', - "boxUL;": '\U0000255D', - "boxUR;": '\U0000255A', - "boxUl;": '\U0000255C', - "boxUr;": '\U00002559', - "boxV;": '\U00002551', - "boxVH;": '\U0000256C', - "boxVL;": '\U00002563', - "boxVR;": '\U00002560', - "boxVh;": '\U0000256B', - "boxVl;": '\U00002562', - "boxVr;": '\U0000255F', - "boxbox;": '\U000029C9', - "boxdL;": '\U00002555', - "boxdR;": '\U00002552', - "boxdl;": '\U00002510', - "boxdr;": '\U0000250C', - "boxh;": '\U00002500', - "boxhD;": '\U00002565', - "boxhU;": '\U00002568', - "boxhd;": '\U0000252C', - "boxhu;": '\U00002534', - "boxminus;": '\U0000229F', - "boxplus;": '\U0000229E', - "boxtimes;": '\U000022A0', - "boxuL;": '\U0000255B', - "boxuR;": '\U00002558', - "boxul;": '\U00002518', - "boxur;": '\U00002514', - "boxv;": '\U00002502', - "boxvH;": '\U0000256A', - "boxvL;": '\U00002561', - "boxvR;": '\U0000255E', - "boxvh;": '\U0000253C', - "boxvl;": '\U00002524', - "boxvr;": '\U0000251C', - "bprime;": '\U00002035', - "breve;": '\U000002D8', - "brvbar;": '\U000000A6', - "bscr;": '\U0001D4B7', - "bsemi;": '\U0000204F', - "bsim;": '\U0000223D', - "bsime;": '\U000022CD', - "bsol;": '\U0000005C', - "bsolb;": '\U000029C5', - "bsolhsub;": '\U000027C8', - "bull;": '\U00002022', - "bullet;": '\U00002022', - "bump;": '\U0000224E', - "bumpE;": '\U00002AAE', - "bumpe;": '\U0000224F', - "bumpeq;": '\U0000224F', - "cacute;": '\U00000107', - "cap;": '\U00002229', - "capand;": '\U00002A44', - "capbrcup;": '\U00002A49', - "capcap;": '\U00002A4B', - "capcup;": '\U00002A47', - "capdot;": '\U00002A40', - "caret;": '\U00002041', - "caron;": '\U000002C7', - "ccaps;": '\U00002A4D', - "ccaron;": '\U0000010D', - "ccedil;": '\U000000E7', - "ccirc;": '\U00000109', - "ccups;": '\U00002A4C', - "ccupssm;": '\U00002A50', - "cdot;": '\U0000010B', - "cedil;": '\U000000B8', - "cemptyv;": '\U000029B2', - "cent;": '\U000000A2', - "centerdot;": '\U000000B7', - "cfr;": '\U0001D520', - "chcy;": '\U00000447', - "check;": '\U00002713', - "checkmark;": '\U00002713', - "chi;": '\U000003C7', - "cir;": '\U000025CB', - "cirE;": '\U000029C3', - "circ;": '\U000002C6', - "circeq;": '\U00002257', - "circlearrowleft;": '\U000021BA', - "circlearrowright;": '\U000021BB', - "circledR;": '\U000000AE', - "circledS;": '\U000024C8', - "circledast;": '\U0000229B', - "circledcirc;": '\U0000229A', - "circleddash;": '\U0000229D', - "cire;": '\U00002257', - "cirfnint;": '\U00002A10', - "cirmid;": '\U00002AEF', - "cirscir;": '\U000029C2', - "clubs;": '\U00002663', - "clubsuit;": '\U00002663', - "colon;": '\U0000003A', - "colone;": '\U00002254', - "coloneq;": '\U00002254', - "comma;": '\U0000002C', - "commat;": '\U00000040', - "comp;": '\U00002201', - "compfn;": '\U00002218', - "complement;": '\U00002201', - "complexes;": '\U00002102', - "cong;": '\U00002245', - "congdot;": '\U00002A6D', - "conint;": '\U0000222E', - "copf;": '\U0001D554', - "coprod;": '\U00002210', - "copy;": '\U000000A9', - "copysr;": '\U00002117', - "crarr;": '\U000021B5', - "cross;": '\U00002717', - "cscr;": '\U0001D4B8', - "csub;": '\U00002ACF', - "csube;": '\U00002AD1', - "csup;": '\U00002AD0', - "csupe;": '\U00002AD2', - "ctdot;": '\U000022EF', - "cudarrl;": '\U00002938', - "cudarrr;": '\U00002935', - "cuepr;": '\U000022DE', - "cuesc;": '\U000022DF', - "cularr;": '\U000021B6', - "cularrp;": '\U0000293D', - "cup;": '\U0000222A', - "cupbrcap;": '\U00002A48', - "cupcap;": '\U00002A46', - "cupcup;": '\U00002A4A', - "cupdot;": '\U0000228D', - "cupor;": '\U00002A45', - "curarr;": '\U000021B7', - "curarrm;": '\U0000293C', - "curlyeqprec;": '\U000022DE', - "curlyeqsucc;": '\U000022DF', - "curlyvee;": '\U000022CE', - "curlywedge;": '\U000022CF', - "curren;": '\U000000A4', - "curvearrowleft;": '\U000021B6', - "curvearrowright;": '\U000021B7', - "cuvee;": '\U000022CE', - "cuwed;": '\U000022CF', - "cwconint;": '\U00002232', - "cwint;": '\U00002231', - "cylcty;": '\U0000232D', - "dArr;": '\U000021D3', - "dHar;": '\U00002965', - "dagger;": '\U00002020', - "daleth;": '\U00002138', - "darr;": '\U00002193', - "dash;": '\U00002010', - "dashv;": '\U000022A3', - "dbkarow;": '\U0000290F', - "dblac;": '\U000002DD', - "dcaron;": '\U0000010F', - "dcy;": '\U00000434', - "dd;": '\U00002146', - "ddagger;": '\U00002021', - "ddarr;": '\U000021CA', - "ddotseq;": '\U00002A77', - "deg;": '\U000000B0', - "delta;": '\U000003B4', - "demptyv;": '\U000029B1', - "dfisht;": '\U0000297F', - "dfr;": '\U0001D521', - "dharl;": '\U000021C3', - "dharr;": '\U000021C2', - "diam;": '\U000022C4', - "diamond;": '\U000022C4', - "diamondsuit;": '\U00002666', - "diams;": '\U00002666', - "die;": '\U000000A8', - "digamma;": '\U000003DD', - "disin;": '\U000022F2', - "div;": '\U000000F7', - "divide;": '\U000000F7', - "divideontimes;": '\U000022C7', - "divonx;": '\U000022C7', - "djcy;": '\U00000452', - "dlcorn;": '\U0000231E', - "dlcrop;": '\U0000230D', - "dollar;": '\U00000024', - "dopf;": '\U0001D555', - "dot;": '\U000002D9', - "doteq;": '\U00002250', - "doteqdot;": '\U00002251', - "dotminus;": '\U00002238', - "dotplus;": '\U00002214', - "dotsquare;": '\U000022A1', - "doublebarwedge;": '\U00002306', - "downarrow;": '\U00002193', - "downdownarrows;": '\U000021CA', - "downharpoonleft;": '\U000021C3', - "downharpoonright;": '\U000021C2', - "drbkarow;": '\U00002910', - "drcorn;": '\U0000231F', - "drcrop;": '\U0000230C', - "dscr;": '\U0001D4B9', - "dscy;": '\U00000455', - "dsol;": '\U000029F6', - "dstrok;": '\U00000111', - "dtdot;": '\U000022F1', - "dtri;": '\U000025BF', - "dtrif;": '\U000025BE', - "duarr;": '\U000021F5', - "duhar;": '\U0000296F', - "dwangle;": '\U000029A6', - "dzcy;": '\U0000045F', - "dzigrarr;": '\U000027FF', - "eDDot;": '\U00002A77', - "eDot;": '\U00002251', - "eacute;": '\U000000E9', - "easter;": '\U00002A6E', - "ecaron;": '\U0000011B', - "ecir;": '\U00002256', - "ecirc;": '\U000000EA', - "ecolon;": '\U00002255', - "ecy;": '\U0000044D', - "edot;": '\U00000117', - "ee;": '\U00002147', - "efDot;": '\U00002252', - "efr;": '\U0001D522', - "eg;": '\U00002A9A', - "egrave;": '\U000000E8', - "egs;": '\U00002A96', - "egsdot;": '\U00002A98', - "el;": '\U00002A99', - "elinters;": '\U000023E7', - "ell;": '\U00002113', - "els;": '\U00002A95', - "elsdot;": '\U00002A97', - "emacr;": '\U00000113', - "empty;": '\U00002205', - "emptyset;": '\U00002205', - "emptyv;": '\U00002205', - "emsp;": '\U00002003', - "emsp13;": '\U00002004', - "emsp14;": '\U00002005', - "eng;": '\U0000014B', - "ensp;": '\U00002002', - "eogon;": '\U00000119', - "eopf;": '\U0001D556', - "epar;": '\U000022D5', - "eparsl;": '\U000029E3', - "eplus;": '\U00002A71', - "epsi;": '\U000003B5', - "epsilon;": '\U000003B5', - "epsiv;": '\U000003F5', - "eqcirc;": '\U00002256', - "eqcolon;": '\U00002255', - "eqsim;": '\U00002242', - "eqslantgtr;": '\U00002A96', - "eqslantless;": '\U00002A95', - "equals;": '\U0000003D', - "equest;": '\U0000225F', - "equiv;": '\U00002261', - "equivDD;": '\U00002A78', - "eqvparsl;": '\U000029E5', - "erDot;": '\U00002253', - "erarr;": '\U00002971', - "escr;": '\U0000212F', - "esdot;": '\U00002250', - "esim;": '\U00002242', - "eta;": '\U000003B7', - "eth;": '\U000000F0', - "euml;": '\U000000EB', - "euro;": '\U000020AC', - "excl;": '\U00000021', - "exist;": '\U00002203', - "expectation;": '\U00002130', - "exponentiale;": '\U00002147', - "fallingdotseq;": '\U00002252', - "fcy;": '\U00000444', - "female;": '\U00002640', - "ffilig;": '\U0000FB03', - "fflig;": '\U0000FB00', - "ffllig;": '\U0000FB04', - "ffr;": '\U0001D523', - "filig;": '\U0000FB01', - "flat;": '\U0000266D', - "fllig;": '\U0000FB02', - "fltns;": '\U000025B1', - "fnof;": '\U00000192', - "fopf;": '\U0001D557', - "forall;": '\U00002200', - "fork;": '\U000022D4', - "forkv;": '\U00002AD9', - "fpartint;": '\U00002A0D', - "frac12;": '\U000000BD', - "frac13;": '\U00002153', - "frac14;": '\U000000BC', - "frac15;": '\U00002155', - "frac16;": '\U00002159', - "frac18;": '\U0000215B', - "frac23;": '\U00002154', - "frac25;": '\U00002156', - "frac34;": '\U000000BE', - "frac35;": '\U00002157', - "frac38;": '\U0000215C', - "frac45;": '\U00002158', - "frac56;": '\U0000215A', - "frac58;": '\U0000215D', - "frac78;": '\U0000215E', - "frasl;": '\U00002044', - "frown;": '\U00002322', - "fscr;": '\U0001D4BB', - "gE;": '\U00002267', - "gEl;": '\U00002A8C', - "gacute;": '\U000001F5', - "gamma;": '\U000003B3', - "gammad;": '\U000003DD', - "gap;": '\U00002A86', - "gbreve;": '\U0000011F', - "gcirc;": '\U0000011D', - "gcy;": '\U00000433', - "gdot;": '\U00000121', - "ge;": '\U00002265', - "gel;": '\U000022DB', - "geq;": '\U00002265', - "geqq;": '\U00002267', - "geqslant;": '\U00002A7E', - "ges;": '\U00002A7E', - "gescc;": '\U00002AA9', - "gesdot;": '\U00002A80', - "gesdoto;": '\U00002A82', - "gesdotol;": '\U00002A84', - "gesles;": '\U00002A94', - "gfr;": '\U0001D524', - "gg;": '\U0000226B', - "ggg;": '\U000022D9', - "gimel;": '\U00002137', - "gjcy;": '\U00000453', - "gl;": '\U00002277', - "glE;": '\U00002A92', - "gla;": '\U00002AA5', - "glj;": '\U00002AA4', - "gnE;": '\U00002269', - "gnap;": '\U00002A8A', - "gnapprox;": '\U00002A8A', - "gne;": '\U00002A88', - "gneq;": '\U00002A88', - "gneqq;": '\U00002269', - "gnsim;": '\U000022E7', - "gopf;": '\U0001D558', - "grave;": '\U00000060', - "gscr;": '\U0000210A', - "gsim;": '\U00002273', - "gsime;": '\U00002A8E', - "gsiml;": '\U00002A90', - "gt;": '\U0000003E', - "gtcc;": '\U00002AA7', - "gtcir;": '\U00002A7A', - "gtdot;": '\U000022D7', - "gtlPar;": '\U00002995', - "gtquest;": '\U00002A7C', - "gtrapprox;": '\U00002A86', - "gtrarr;": '\U00002978', - "gtrdot;": '\U000022D7', - "gtreqless;": '\U000022DB', - "gtreqqless;": '\U00002A8C', - "gtrless;": '\U00002277', - "gtrsim;": '\U00002273', - "hArr;": '\U000021D4', - "hairsp;": '\U0000200A', - "half;": '\U000000BD', - "hamilt;": '\U0000210B', - "hardcy;": '\U0000044A', - "harr;": '\U00002194', - "harrcir;": '\U00002948', - "harrw;": '\U000021AD', - "hbar;": '\U0000210F', - "hcirc;": '\U00000125', - "hearts;": '\U00002665', - "heartsuit;": '\U00002665', - "hellip;": '\U00002026', - "hercon;": '\U000022B9', - "hfr;": '\U0001D525', - "hksearow;": '\U00002925', - "hkswarow;": '\U00002926', - "hoarr;": '\U000021FF', - "homtht;": '\U0000223B', - "hookleftarrow;": '\U000021A9', - "hookrightarrow;": '\U000021AA', - "hopf;": '\U0001D559', - "horbar;": '\U00002015', - "hscr;": '\U0001D4BD', - "hslash;": '\U0000210F', - "hstrok;": '\U00000127', - "hybull;": '\U00002043', - "hyphen;": '\U00002010', - "iacute;": '\U000000ED', - "ic;": '\U00002063', - "icirc;": '\U000000EE', - "icy;": '\U00000438', - "iecy;": '\U00000435', - "iexcl;": '\U000000A1', - "iff;": '\U000021D4', - "ifr;": '\U0001D526', - "igrave;": '\U000000EC', - "ii;": '\U00002148', - "iiiint;": '\U00002A0C', - "iiint;": '\U0000222D', - "iinfin;": '\U000029DC', - "iiota;": '\U00002129', - "ijlig;": '\U00000133', - "imacr;": '\U0000012B', - "image;": '\U00002111', - "imagline;": '\U00002110', - "imagpart;": '\U00002111', - "imath;": '\U00000131', - "imof;": '\U000022B7', - "imped;": '\U000001B5', - "in;": '\U00002208', - "incare;": '\U00002105', - "infin;": '\U0000221E', - "infintie;": '\U000029DD', - "inodot;": '\U00000131', - "int;": '\U0000222B', - "intcal;": '\U000022BA', - "integers;": '\U00002124', - "intercal;": '\U000022BA', - "intlarhk;": '\U00002A17', - "intprod;": '\U00002A3C', - "iocy;": '\U00000451', - "iogon;": '\U0000012F', - "iopf;": '\U0001D55A', - "iota;": '\U000003B9', - "iprod;": '\U00002A3C', - "iquest;": '\U000000BF', - "iscr;": '\U0001D4BE', - "isin;": '\U00002208', - "isinE;": '\U000022F9', - "isindot;": '\U000022F5', - "isins;": '\U000022F4', - "isinsv;": '\U000022F3', - "isinv;": '\U00002208', - "it;": '\U00002062', - "itilde;": '\U00000129', - "iukcy;": '\U00000456', - "iuml;": '\U000000EF', - "jcirc;": '\U00000135', - "jcy;": '\U00000439', - "jfr;": '\U0001D527', - "jmath;": '\U00000237', - "jopf;": '\U0001D55B', - "jscr;": '\U0001D4BF', - "jsercy;": '\U00000458', - "jukcy;": '\U00000454', - "kappa;": '\U000003BA', - "kappav;": '\U000003F0', - "kcedil;": '\U00000137', - "kcy;": '\U0000043A', - "kfr;": '\U0001D528', - "kgreen;": '\U00000138', - "khcy;": '\U00000445', - "kjcy;": '\U0000045C', - "kopf;": '\U0001D55C', - "kscr;": '\U0001D4C0', - "lAarr;": '\U000021DA', - "lArr;": '\U000021D0', - "lAtail;": '\U0000291B', - "lBarr;": '\U0000290E', - "lE;": '\U00002266', - "lEg;": '\U00002A8B', - "lHar;": '\U00002962', - "lacute;": '\U0000013A', - "laemptyv;": '\U000029B4', - "lagran;": '\U00002112', - "lambda;": '\U000003BB', - "lang;": '\U000027E8', - "langd;": '\U00002991', - "langle;": '\U000027E8', - "lap;": '\U00002A85', - "laquo;": '\U000000AB', - "larr;": '\U00002190', - "larrb;": '\U000021E4', - "larrbfs;": '\U0000291F', - "larrfs;": '\U0000291D', - "larrhk;": '\U000021A9', - "larrlp;": '\U000021AB', - "larrpl;": '\U00002939', - "larrsim;": '\U00002973', - "larrtl;": '\U000021A2', - "lat;": '\U00002AAB', - "latail;": '\U00002919', - "late;": '\U00002AAD', - "lbarr;": '\U0000290C', - "lbbrk;": '\U00002772', - "lbrace;": '\U0000007B', - "lbrack;": '\U0000005B', - "lbrke;": '\U0000298B', - "lbrksld;": '\U0000298F', - "lbrkslu;": '\U0000298D', - "lcaron;": '\U0000013E', - "lcedil;": '\U0000013C', - "lceil;": '\U00002308', - "lcub;": '\U0000007B', - "lcy;": '\U0000043B', - "ldca;": '\U00002936', - "ldquo;": '\U0000201C', - "ldquor;": '\U0000201E', - "ldrdhar;": '\U00002967', - "ldrushar;": '\U0000294B', - "ldsh;": '\U000021B2', - "le;": '\U00002264', - "leftarrow;": '\U00002190', - "leftarrowtail;": '\U000021A2', - "leftharpoondown;": '\U000021BD', - "leftharpoonup;": '\U000021BC', - "leftleftarrows;": '\U000021C7', - "leftrightarrow;": '\U00002194', - "leftrightarrows;": '\U000021C6', - "leftrightharpoons;": '\U000021CB', - "leftrightsquigarrow;": '\U000021AD', - "leftthreetimes;": '\U000022CB', - "leg;": '\U000022DA', - "leq;": '\U00002264', - "leqq;": '\U00002266', - "leqslant;": '\U00002A7D', - "les;": '\U00002A7D', - "lescc;": '\U00002AA8', - "lesdot;": '\U00002A7F', - "lesdoto;": '\U00002A81', - "lesdotor;": '\U00002A83', - "lesges;": '\U00002A93', - "lessapprox;": '\U00002A85', - "lessdot;": '\U000022D6', - "lesseqgtr;": '\U000022DA', - "lesseqqgtr;": '\U00002A8B', - "lessgtr;": '\U00002276', - "lesssim;": '\U00002272', - "lfisht;": '\U0000297C', - "lfloor;": '\U0000230A', - "lfr;": '\U0001D529', - "lg;": '\U00002276', - "lgE;": '\U00002A91', - "lhard;": '\U000021BD', - "lharu;": '\U000021BC', - "lharul;": '\U0000296A', - "lhblk;": '\U00002584', - "ljcy;": '\U00000459', - "ll;": '\U0000226A', - "llarr;": '\U000021C7', - "llcorner;": '\U0000231E', - "llhard;": '\U0000296B', - "lltri;": '\U000025FA', - "lmidot;": '\U00000140', - "lmoust;": '\U000023B0', - "lmoustache;": '\U000023B0', - "lnE;": '\U00002268', - "lnap;": '\U00002A89', - "lnapprox;": '\U00002A89', - "lne;": '\U00002A87', - "lneq;": '\U00002A87', - "lneqq;": '\U00002268', - "lnsim;": '\U000022E6', - "loang;": '\U000027EC', - "loarr;": '\U000021FD', - "lobrk;": '\U000027E6', - "longleftarrow;": '\U000027F5', - "longleftrightarrow;": '\U000027F7', - "longmapsto;": '\U000027FC', - "longrightarrow;": '\U000027F6', - "looparrowleft;": '\U000021AB', - "looparrowright;": '\U000021AC', - "lopar;": '\U00002985', - "lopf;": '\U0001D55D', - "loplus;": '\U00002A2D', - "lotimes;": '\U00002A34', - "lowast;": '\U00002217', - "lowbar;": '\U0000005F', - "loz;": '\U000025CA', - "lozenge;": '\U000025CA', - "lozf;": '\U000029EB', - "lpar;": '\U00000028', - "lparlt;": '\U00002993', - "lrarr;": '\U000021C6', - "lrcorner;": '\U0000231F', - "lrhar;": '\U000021CB', - "lrhard;": '\U0000296D', - "lrm;": '\U0000200E', - "lrtri;": '\U000022BF', - "lsaquo;": '\U00002039', - "lscr;": '\U0001D4C1', - "lsh;": '\U000021B0', - "lsim;": '\U00002272', - "lsime;": '\U00002A8D', - "lsimg;": '\U00002A8F', - "lsqb;": '\U0000005B', - "lsquo;": '\U00002018', - "lsquor;": '\U0000201A', - "lstrok;": '\U00000142', - "lt;": '\U0000003C', - "ltcc;": '\U00002AA6', - "ltcir;": '\U00002A79', - "ltdot;": '\U000022D6', - "lthree;": '\U000022CB', - "ltimes;": '\U000022C9', - "ltlarr;": '\U00002976', - "ltquest;": '\U00002A7B', - "ltrPar;": '\U00002996', - "ltri;": '\U000025C3', - "ltrie;": '\U000022B4', - "ltrif;": '\U000025C2', - "lurdshar;": '\U0000294A', - "luruhar;": '\U00002966', - "mDDot;": '\U0000223A', - "macr;": '\U000000AF', - "male;": '\U00002642', - "malt;": '\U00002720', - "maltese;": '\U00002720', - "map;": '\U000021A6', - "mapsto;": '\U000021A6', - "mapstodown;": '\U000021A7', - "mapstoleft;": '\U000021A4', - "mapstoup;": '\U000021A5', - "marker;": '\U000025AE', - "mcomma;": '\U00002A29', - "mcy;": '\U0000043C', - "mdash;": '\U00002014', - "measuredangle;": '\U00002221', - "mfr;": '\U0001D52A', - "mho;": '\U00002127', - "micro;": '\U000000B5', - "mid;": '\U00002223', - "midast;": '\U0000002A', - "midcir;": '\U00002AF0', - "middot;": '\U000000B7', - "minus;": '\U00002212', - "minusb;": '\U0000229F', - "minusd;": '\U00002238', - "minusdu;": '\U00002A2A', - "mlcp;": '\U00002ADB', - "mldr;": '\U00002026', - "mnplus;": '\U00002213', - "models;": '\U000022A7', - "mopf;": '\U0001D55E', - "mp;": '\U00002213', - "mscr;": '\U0001D4C2', - "mstpos;": '\U0000223E', - "mu;": '\U000003BC', - "multimap;": '\U000022B8', - "mumap;": '\U000022B8', - "nLeftarrow;": '\U000021CD', - "nLeftrightarrow;": '\U000021CE', - "nRightarrow;": '\U000021CF', - "nVDash;": '\U000022AF', - "nVdash;": '\U000022AE', - "nabla;": '\U00002207', - "nacute;": '\U00000144', - "nap;": '\U00002249', - "napos;": '\U00000149', - "napprox;": '\U00002249', - "natur;": '\U0000266E', - "natural;": '\U0000266E', - "naturals;": '\U00002115', - "nbsp;": '\U000000A0', - "ncap;": '\U00002A43', - "ncaron;": '\U00000148', - "ncedil;": '\U00000146', - "ncong;": '\U00002247', - "ncup;": '\U00002A42', - "ncy;": '\U0000043D', - "ndash;": '\U00002013', - "ne;": '\U00002260', - "neArr;": '\U000021D7', - "nearhk;": '\U00002924', - "nearr;": '\U00002197', - "nearrow;": '\U00002197', - "nequiv;": '\U00002262', - "nesear;": '\U00002928', - "nexist;": '\U00002204', - "nexists;": '\U00002204', - "nfr;": '\U0001D52B', - "nge;": '\U00002271', - "ngeq;": '\U00002271', - "ngsim;": '\U00002275', - "ngt;": '\U0000226F', - "ngtr;": '\U0000226F', - "nhArr;": '\U000021CE', - "nharr;": '\U000021AE', - "nhpar;": '\U00002AF2', - "ni;": '\U0000220B', - "nis;": '\U000022FC', - "nisd;": '\U000022FA', - "niv;": '\U0000220B', - "njcy;": '\U0000045A', - "nlArr;": '\U000021CD', - "nlarr;": '\U0000219A', - "nldr;": '\U00002025', - "nle;": '\U00002270', - "nleftarrow;": '\U0000219A', - "nleftrightarrow;": '\U000021AE', - "nleq;": '\U00002270', - "nless;": '\U0000226E', - "nlsim;": '\U00002274', - "nlt;": '\U0000226E', - "nltri;": '\U000022EA', - "nltrie;": '\U000022EC', - "nmid;": '\U00002224', - "nopf;": '\U0001D55F', - "not;": '\U000000AC', - "notin;": '\U00002209', - "notinva;": '\U00002209', - "notinvb;": '\U000022F7', - "notinvc;": '\U000022F6', - "notni;": '\U0000220C', - "notniva;": '\U0000220C', - "notnivb;": '\U000022FE', - "notnivc;": '\U000022FD', - "npar;": '\U00002226', - "nparallel;": '\U00002226', - "npolint;": '\U00002A14', - "npr;": '\U00002280', - "nprcue;": '\U000022E0', - "nprec;": '\U00002280', - "nrArr;": '\U000021CF', - "nrarr;": '\U0000219B', - "nrightarrow;": '\U0000219B', - "nrtri;": '\U000022EB', - "nrtrie;": '\U000022ED', - "nsc;": '\U00002281', - "nsccue;": '\U000022E1', - "nscr;": '\U0001D4C3', - "nshortmid;": '\U00002224', - "nshortparallel;": '\U00002226', - "nsim;": '\U00002241', - "nsime;": '\U00002244', - "nsimeq;": '\U00002244', - "nsmid;": '\U00002224', - "nspar;": '\U00002226', - "nsqsube;": '\U000022E2', - "nsqsupe;": '\U000022E3', - "nsub;": '\U00002284', - "nsube;": '\U00002288', - "nsubseteq;": '\U00002288', - "nsucc;": '\U00002281', - "nsup;": '\U00002285', - "nsupe;": '\U00002289', - "nsupseteq;": '\U00002289', - "ntgl;": '\U00002279', - "ntilde;": '\U000000F1', - "ntlg;": '\U00002278', - "ntriangleleft;": '\U000022EA', - "ntrianglelefteq;": '\U000022EC', - "ntriangleright;": '\U000022EB', - "ntrianglerighteq;": '\U000022ED', - "nu;": '\U000003BD', - "num;": '\U00000023', - "numero;": '\U00002116', - "numsp;": '\U00002007', - "nvDash;": '\U000022AD', - "nvHarr;": '\U00002904', - "nvdash;": '\U000022AC', - "nvinfin;": '\U000029DE', - "nvlArr;": '\U00002902', - "nvrArr;": '\U00002903', - "nwArr;": '\U000021D6', - "nwarhk;": '\U00002923', - "nwarr;": '\U00002196', - "nwarrow;": '\U00002196', - "nwnear;": '\U00002927', - "oS;": '\U000024C8', - "oacute;": '\U000000F3', - "oast;": '\U0000229B', - "ocir;": '\U0000229A', - "ocirc;": '\U000000F4', - "ocy;": '\U0000043E', - "odash;": '\U0000229D', - "odblac;": '\U00000151', - "odiv;": '\U00002A38', - "odot;": '\U00002299', - "odsold;": '\U000029BC', - "oelig;": '\U00000153', - "ofcir;": '\U000029BF', - "ofr;": '\U0001D52C', - "ogon;": '\U000002DB', - "ograve;": '\U000000F2', - "ogt;": '\U000029C1', - "ohbar;": '\U000029B5', - "ohm;": '\U000003A9', - "oint;": '\U0000222E', - "olarr;": '\U000021BA', - "olcir;": '\U000029BE', - "olcross;": '\U000029BB', - "oline;": '\U0000203E', - "olt;": '\U000029C0', - "omacr;": '\U0000014D', - "omega;": '\U000003C9', - "omicron;": '\U000003BF', - "omid;": '\U000029B6', - "ominus;": '\U00002296', - "oopf;": '\U0001D560', - "opar;": '\U000029B7', - "operp;": '\U000029B9', - "oplus;": '\U00002295', - "or;": '\U00002228', - "orarr;": '\U000021BB', - "ord;": '\U00002A5D', - "order;": '\U00002134', - "orderof;": '\U00002134', - "ordf;": '\U000000AA', - "ordm;": '\U000000BA', - "origof;": '\U000022B6', - "oror;": '\U00002A56', - "orslope;": '\U00002A57', - "orv;": '\U00002A5B', - "oscr;": '\U00002134', - "oslash;": '\U000000F8', - "osol;": '\U00002298', - "otilde;": '\U000000F5', - "otimes;": '\U00002297', - "otimesas;": '\U00002A36', - "ouml;": '\U000000F6', - "ovbar;": '\U0000233D', - "par;": '\U00002225', - "para;": '\U000000B6', - "parallel;": '\U00002225', - "parsim;": '\U00002AF3', - "parsl;": '\U00002AFD', - "part;": '\U00002202', - "pcy;": '\U0000043F', - "percnt;": '\U00000025', - "period;": '\U0000002E', - "permil;": '\U00002030', - "perp;": '\U000022A5', - "pertenk;": '\U00002031', - "pfr;": '\U0001D52D', - "phi;": '\U000003C6', - "phiv;": '\U000003D5', - "phmmat;": '\U00002133', - "phone;": '\U0000260E', - "pi;": '\U000003C0', - "pitchfork;": '\U000022D4', - "piv;": '\U000003D6', - "planck;": '\U0000210F', - "planckh;": '\U0000210E', - "plankv;": '\U0000210F', - "plus;": '\U0000002B', - "plusacir;": '\U00002A23', - "plusb;": '\U0000229E', - "pluscir;": '\U00002A22', - "plusdo;": '\U00002214', - "plusdu;": '\U00002A25', - "pluse;": '\U00002A72', - "plusmn;": '\U000000B1', - "plussim;": '\U00002A26', - "plustwo;": '\U00002A27', - "pm;": '\U000000B1', - "pointint;": '\U00002A15', - "popf;": '\U0001D561', - "pound;": '\U000000A3', - "pr;": '\U0000227A', - "prE;": '\U00002AB3', - "prap;": '\U00002AB7', - "prcue;": '\U0000227C', - "pre;": '\U00002AAF', - "prec;": '\U0000227A', - "precapprox;": '\U00002AB7', - "preccurlyeq;": '\U0000227C', - "preceq;": '\U00002AAF', - "precnapprox;": '\U00002AB9', - "precneqq;": '\U00002AB5', - "precnsim;": '\U000022E8', - "precsim;": '\U0000227E', - "prime;": '\U00002032', - "primes;": '\U00002119', - "prnE;": '\U00002AB5', - "prnap;": '\U00002AB9', - "prnsim;": '\U000022E8', - "prod;": '\U0000220F', - "profalar;": '\U0000232E', - "profline;": '\U00002312', - "profsurf;": '\U00002313', - "prop;": '\U0000221D', - "propto;": '\U0000221D', - "prsim;": '\U0000227E', - "prurel;": '\U000022B0', - "pscr;": '\U0001D4C5', - "psi;": '\U000003C8', - "puncsp;": '\U00002008', - "qfr;": '\U0001D52E', - "qint;": '\U00002A0C', - "qopf;": '\U0001D562', - "qprime;": '\U00002057', - "qscr;": '\U0001D4C6', - "quaternions;": '\U0000210D', - "quatint;": '\U00002A16', - "quest;": '\U0000003F', - "questeq;": '\U0000225F', - "quot;": '\U00000022', - "rAarr;": '\U000021DB', - "rArr;": '\U000021D2', - "rAtail;": '\U0000291C', - "rBarr;": '\U0000290F', - "rHar;": '\U00002964', - "racute;": '\U00000155', - "radic;": '\U0000221A', - "raemptyv;": '\U000029B3', - "rang;": '\U000027E9', - "rangd;": '\U00002992', - "range;": '\U000029A5', - "rangle;": '\U000027E9', - "raquo;": '\U000000BB', - "rarr;": '\U00002192', - "rarrap;": '\U00002975', - "rarrb;": '\U000021E5', - "rarrbfs;": '\U00002920', - "rarrc;": '\U00002933', - "rarrfs;": '\U0000291E', - "rarrhk;": '\U000021AA', - "rarrlp;": '\U000021AC', - "rarrpl;": '\U00002945', - "rarrsim;": '\U00002974', - "rarrtl;": '\U000021A3', - "rarrw;": '\U0000219D', - "ratail;": '\U0000291A', - "ratio;": '\U00002236', - "rationals;": '\U0000211A', - "rbarr;": '\U0000290D', - "rbbrk;": '\U00002773', - "rbrace;": '\U0000007D', - "rbrack;": '\U0000005D', - "rbrke;": '\U0000298C', - "rbrksld;": '\U0000298E', - "rbrkslu;": '\U00002990', - "rcaron;": '\U00000159', - "rcedil;": '\U00000157', - "rceil;": '\U00002309', - "rcub;": '\U0000007D', - "rcy;": '\U00000440', - "rdca;": '\U00002937', - "rdldhar;": '\U00002969', - "rdquo;": '\U0000201D', - "rdquor;": '\U0000201D', - "rdsh;": '\U000021B3', - "real;": '\U0000211C', - "realine;": '\U0000211B', - "realpart;": '\U0000211C', - "reals;": '\U0000211D', - "rect;": '\U000025AD', - "reg;": '\U000000AE', - "rfisht;": '\U0000297D', - "rfloor;": '\U0000230B', - "rfr;": '\U0001D52F', - "rhard;": '\U000021C1', - "rharu;": '\U000021C0', - "rharul;": '\U0000296C', - "rho;": '\U000003C1', - "rhov;": '\U000003F1', - "rightarrow;": '\U00002192', - "rightarrowtail;": '\U000021A3', - "rightharpoondown;": '\U000021C1', - "rightharpoonup;": '\U000021C0', - "rightleftarrows;": '\U000021C4', - "rightleftharpoons;": '\U000021CC', - "rightrightarrows;": '\U000021C9', - "rightsquigarrow;": '\U0000219D', - "rightthreetimes;": '\U000022CC', - "ring;": '\U000002DA', - "risingdotseq;": '\U00002253', - "rlarr;": '\U000021C4', - "rlhar;": '\U000021CC', - "rlm;": '\U0000200F', - "rmoust;": '\U000023B1', - "rmoustache;": '\U000023B1', - "rnmid;": '\U00002AEE', - "roang;": '\U000027ED', - "roarr;": '\U000021FE', - "robrk;": '\U000027E7', - "ropar;": '\U00002986', - "ropf;": '\U0001D563', - "roplus;": '\U00002A2E', - "rotimes;": '\U00002A35', - "rpar;": '\U00000029', - "rpargt;": '\U00002994', - "rppolint;": '\U00002A12', - "rrarr;": '\U000021C9', - "rsaquo;": '\U0000203A', - "rscr;": '\U0001D4C7', - "rsh;": '\U000021B1', - "rsqb;": '\U0000005D', - "rsquo;": '\U00002019', - "rsquor;": '\U00002019', - "rthree;": '\U000022CC', - "rtimes;": '\U000022CA', - "rtri;": '\U000025B9', - "rtrie;": '\U000022B5', - "rtrif;": '\U000025B8', - "rtriltri;": '\U000029CE', - "ruluhar;": '\U00002968', - "rx;": '\U0000211E', - "sacute;": '\U0000015B', - "sbquo;": '\U0000201A', - "sc;": '\U0000227B', - "scE;": '\U00002AB4', - "scap;": '\U00002AB8', - "scaron;": '\U00000161', - "sccue;": '\U0000227D', - "sce;": '\U00002AB0', - "scedil;": '\U0000015F', - "scirc;": '\U0000015D', - "scnE;": '\U00002AB6', - "scnap;": '\U00002ABA', - "scnsim;": '\U000022E9', - "scpolint;": '\U00002A13', - "scsim;": '\U0000227F', - "scy;": '\U00000441', - "sdot;": '\U000022C5', - "sdotb;": '\U000022A1', - "sdote;": '\U00002A66', - "seArr;": '\U000021D8', - "searhk;": '\U00002925', - "searr;": '\U00002198', - "searrow;": '\U00002198', - "sect;": '\U000000A7', - "semi;": '\U0000003B', - "seswar;": '\U00002929', - "setminus;": '\U00002216', - "setmn;": '\U00002216', - "sext;": '\U00002736', - "sfr;": '\U0001D530', - "sfrown;": '\U00002322', - "sharp;": '\U0000266F', - "shchcy;": '\U00000449', - "shcy;": '\U00000448', - "shortmid;": '\U00002223', - "shortparallel;": '\U00002225', - "shy;": '\U000000AD', - "sigma;": '\U000003C3', - "sigmaf;": '\U000003C2', - "sigmav;": '\U000003C2', - "sim;": '\U0000223C', - "simdot;": '\U00002A6A', - "sime;": '\U00002243', - "simeq;": '\U00002243', - "simg;": '\U00002A9E', - "simgE;": '\U00002AA0', - "siml;": '\U00002A9D', - "simlE;": '\U00002A9F', - "simne;": '\U00002246', - "simplus;": '\U00002A24', - "simrarr;": '\U00002972', - "slarr;": '\U00002190', - "smallsetminus;": '\U00002216', - "smashp;": '\U00002A33', - "smeparsl;": '\U000029E4', - "smid;": '\U00002223', - "smile;": '\U00002323', - "smt;": '\U00002AAA', - "smte;": '\U00002AAC', - "softcy;": '\U0000044C', - "sol;": '\U0000002F', - "solb;": '\U000029C4', - "solbar;": '\U0000233F', - "sopf;": '\U0001D564', - "spades;": '\U00002660', - "spadesuit;": '\U00002660', - "spar;": '\U00002225', - "sqcap;": '\U00002293', - "sqcup;": '\U00002294', - "sqsub;": '\U0000228F', - "sqsube;": '\U00002291', - "sqsubset;": '\U0000228F', - "sqsubseteq;": '\U00002291', - "sqsup;": '\U00002290', - "sqsupe;": '\U00002292', - "sqsupset;": '\U00002290', - "sqsupseteq;": '\U00002292', - "squ;": '\U000025A1', - "square;": '\U000025A1', - "squarf;": '\U000025AA', - "squf;": '\U000025AA', - "srarr;": '\U00002192', - "sscr;": '\U0001D4C8', - "ssetmn;": '\U00002216', - "ssmile;": '\U00002323', - "sstarf;": '\U000022C6', - "star;": '\U00002606', - "starf;": '\U00002605', - "straightepsilon;": '\U000003F5', - "straightphi;": '\U000003D5', - "strns;": '\U000000AF', - "sub;": '\U00002282', - "subE;": '\U00002AC5', - "subdot;": '\U00002ABD', - "sube;": '\U00002286', - "subedot;": '\U00002AC3', - "submult;": '\U00002AC1', - "subnE;": '\U00002ACB', - "subne;": '\U0000228A', - "subplus;": '\U00002ABF', - "subrarr;": '\U00002979', - "subset;": '\U00002282', - "subseteq;": '\U00002286', - "subseteqq;": '\U00002AC5', - "subsetneq;": '\U0000228A', - "subsetneqq;": '\U00002ACB', - "subsim;": '\U00002AC7', - "subsub;": '\U00002AD5', - "subsup;": '\U00002AD3', - "succ;": '\U0000227B', - "succapprox;": '\U00002AB8', - "succcurlyeq;": '\U0000227D', - "succeq;": '\U00002AB0', - "succnapprox;": '\U00002ABA', - "succneqq;": '\U00002AB6', - "succnsim;": '\U000022E9', - "succsim;": '\U0000227F', - "sum;": '\U00002211', - "sung;": '\U0000266A', - "sup;": '\U00002283', - "sup1;": '\U000000B9', - "sup2;": '\U000000B2', - "sup3;": '\U000000B3', - "supE;": '\U00002AC6', - "supdot;": '\U00002ABE', - "supdsub;": '\U00002AD8', - "supe;": '\U00002287', - "supedot;": '\U00002AC4', - "suphsol;": '\U000027C9', - "suphsub;": '\U00002AD7', - "suplarr;": '\U0000297B', - "supmult;": '\U00002AC2', - "supnE;": '\U00002ACC', - "supne;": '\U0000228B', - "supplus;": '\U00002AC0', - "supset;": '\U00002283', - "supseteq;": '\U00002287', - "supseteqq;": '\U00002AC6', - "supsetneq;": '\U0000228B', - "supsetneqq;": '\U00002ACC', - "supsim;": '\U00002AC8', - "supsub;": '\U00002AD4', - "supsup;": '\U00002AD6', - "swArr;": '\U000021D9', - "swarhk;": '\U00002926', - "swarr;": '\U00002199', - "swarrow;": '\U00002199', - "swnwar;": '\U0000292A', - "szlig;": '\U000000DF', - "target;": '\U00002316', - "tau;": '\U000003C4', - "tbrk;": '\U000023B4', - "tcaron;": '\U00000165', - "tcedil;": '\U00000163', - "tcy;": '\U00000442', - "tdot;": '\U000020DB', - "telrec;": '\U00002315', - "tfr;": '\U0001D531', - "there4;": '\U00002234', - "therefore;": '\U00002234', - "theta;": '\U000003B8', - "thetasym;": '\U000003D1', - "thetav;": '\U000003D1', - "thickapprox;": '\U00002248', - "thicksim;": '\U0000223C', - "thinsp;": '\U00002009', - "thkap;": '\U00002248', - "thksim;": '\U0000223C', - "thorn;": '\U000000FE', - "tilde;": '\U000002DC', - "times;": '\U000000D7', - "timesb;": '\U000022A0', - "timesbar;": '\U00002A31', - "timesd;": '\U00002A30', - "tint;": '\U0000222D', - "toea;": '\U00002928', - "top;": '\U000022A4', - "topbot;": '\U00002336', - "topcir;": '\U00002AF1', - "topf;": '\U0001D565', - "topfork;": '\U00002ADA', - "tosa;": '\U00002929', - "tprime;": '\U00002034', - "trade;": '\U00002122', - "triangle;": '\U000025B5', - "triangledown;": '\U000025BF', - "triangleleft;": '\U000025C3', - "trianglelefteq;": '\U000022B4', - "triangleq;": '\U0000225C', - "triangleright;": '\U000025B9', - "trianglerighteq;": '\U000022B5', - "tridot;": '\U000025EC', - "trie;": '\U0000225C', - "triminus;": '\U00002A3A', - "triplus;": '\U00002A39', - "trisb;": '\U000029CD', - "tritime;": '\U00002A3B', - "trpezium;": '\U000023E2', - "tscr;": '\U0001D4C9', - "tscy;": '\U00000446', - "tshcy;": '\U0000045B', - "tstrok;": '\U00000167', - "twixt;": '\U0000226C', - "twoheadleftarrow;": '\U0000219E', - "twoheadrightarrow;": '\U000021A0', - "uArr;": '\U000021D1', - "uHar;": '\U00002963', - "uacute;": '\U000000FA', - "uarr;": '\U00002191', - "ubrcy;": '\U0000045E', - "ubreve;": '\U0000016D', - "ucirc;": '\U000000FB', - "ucy;": '\U00000443', - "udarr;": '\U000021C5', - "udblac;": '\U00000171', - "udhar;": '\U0000296E', - "ufisht;": '\U0000297E', - "ufr;": '\U0001D532', - "ugrave;": '\U000000F9', - "uharl;": '\U000021BF', - "uharr;": '\U000021BE', - "uhblk;": '\U00002580', - "ulcorn;": '\U0000231C', - "ulcorner;": '\U0000231C', - "ulcrop;": '\U0000230F', - "ultri;": '\U000025F8', - "umacr;": '\U0000016B', - "uml;": '\U000000A8', - "uogon;": '\U00000173', - "uopf;": '\U0001D566', - "uparrow;": '\U00002191', - "updownarrow;": '\U00002195', - "upharpoonleft;": '\U000021BF', - "upharpoonright;": '\U000021BE', - "uplus;": '\U0000228E', - "upsi;": '\U000003C5', - "upsih;": '\U000003D2', - "upsilon;": '\U000003C5', - "upuparrows;": '\U000021C8', - "urcorn;": '\U0000231D', - "urcorner;": '\U0000231D', - "urcrop;": '\U0000230E', - "uring;": '\U0000016F', - "urtri;": '\U000025F9', - "uscr;": '\U0001D4CA', - "utdot;": '\U000022F0', - "utilde;": '\U00000169', - "utri;": '\U000025B5', - "utrif;": '\U000025B4', - "uuarr;": '\U000021C8', - "uuml;": '\U000000FC', - "uwangle;": '\U000029A7', - "vArr;": '\U000021D5', - "vBar;": '\U00002AE8', - "vBarv;": '\U00002AE9', - "vDash;": '\U000022A8', - "vangrt;": '\U0000299C', - "varepsilon;": '\U000003F5', - "varkappa;": '\U000003F0', - "varnothing;": '\U00002205', - "varphi;": '\U000003D5', - "varpi;": '\U000003D6', - "varpropto;": '\U0000221D', - "varr;": '\U00002195', - "varrho;": '\U000003F1', - "varsigma;": '\U000003C2', - "vartheta;": '\U000003D1', - "vartriangleleft;": '\U000022B2', - "vartriangleright;": '\U000022B3', - "vcy;": '\U00000432', - "vdash;": '\U000022A2', - "vee;": '\U00002228', - "veebar;": '\U000022BB', - "veeeq;": '\U0000225A', - "vellip;": '\U000022EE', - "verbar;": '\U0000007C', - "vert;": '\U0000007C', - "vfr;": '\U0001D533', - "vltri;": '\U000022B2', - "vopf;": '\U0001D567', - "vprop;": '\U0000221D', - "vrtri;": '\U000022B3', - "vscr;": '\U0001D4CB', - "vzigzag;": '\U0000299A', - "wcirc;": '\U00000175', - "wedbar;": '\U00002A5F', - "wedge;": '\U00002227', - "wedgeq;": '\U00002259', - "weierp;": '\U00002118', - "wfr;": '\U0001D534', - "wopf;": '\U0001D568', - "wp;": '\U00002118', - "wr;": '\U00002240', - "wreath;": '\U00002240', - "wscr;": '\U0001D4CC', - "xcap;": '\U000022C2', - "xcirc;": '\U000025EF', - "xcup;": '\U000022C3', - "xdtri;": '\U000025BD', - "xfr;": '\U0001D535', - "xhArr;": '\U000027FA', - "xharr;": '\U000027F7', - "xi;": '\U000003BE', - "xlArr;": '\U000027F8', - "xlarr;": '\U000027F5', - "xmap;": '\U000027FC', - "xnis;": '\U000022FB', - "xodot;": '\U00002A00', - "xopf;": '\U0001D569', - "xoplus;": '\U00002A01', - "xotime;": '\U00002A02', - "xrArr;": '\U000027F9', - "xrarr;": '\U000027F6', - "xscr;": '\U0001D4CD', - "xsqcup;": '\U00002A06', - "xuplus;": '\U00002A04', - "xutri;": '\U000025B3', - "xvee;": '\U000022C1', - "xwedge;": '\U000022C0', - "yacute;": '\U000000FD', - "yacy;": '\U0000044F', - "ycirc;": '\U00000177', - "ycy;": '\U0000044B', - "yen;": '\U000000A5', - "yfr;": '\U0001D536', - "yicy;": '\U00000457', - "yopf;": '\U0001D56A', - "yscr;": '\U0001D4CE', - "yucy;": '\U0000044E', - "yuml;": '\U000000FF', - "zacute;": '\U0000017A', - "zcaron;": '\U0000017E', - "zcy;": '\U00000437', - "zdot;": '\U0000017C', - "zeetrf;": '\U00002128', - "zeta;": '\U000003B6', - "zfr;": '\U0001D537', - "zhcy;": '\U00000436', - "zigrarr;": '\U000021DD', - "zopf;": '\U0001D56B', - "zscr;": '\U0001D4CF', - "zwj;": '\U0000200D', - "zwnj;": '\U0000200C', - "AElig": '\U000000C6', - "AMP": '\U00000026', - "Aacute": '\U000000C1', - "Acirc": '\U000000C2', - "Agrave": '\U000000C0', - "Aring": '\U000000C5', - "Atilde": '\U000000C3', - "Auml": '\U000000C4', - "COPY": '\U000000A9', - "Ccedil": '\U000000C7', - "ETH": '\U000000D0', - "Eacute": '\U000000C9', - "Ecirc": '\U000000CA', - "Egrave": '\U000000C8', - "Euml": '\U000000CB', - "GT": '\U0000003E', - "Iacute": '\U000000CD', - "Icirc": '\U000000CE', - "Igrave": '\U000000CC', - "Iuml": '\U000000CF', - "LT": '\U0000003C', - "Ntilde": '\U000000D1', - "Oacute": '\U000000D3', - "Ocirc": '\U000000D4', - "Ograve": '\U000000D2', - "Oslash": '\U000000D8', - "Otilde": '\U000000D5', - "Ouml": '\U000000D6', - "QUOT": '\U00000022', - "REG": '\U000000AE', - "THORN": '\U000000DE', - "Uacute": '\U000000DA', - "Ucirc": '\U000000DB', - "Ugrave": '\U000000D9', - "Uuml": '\U000000DC', - "Yacute": '\U000000DD', - "aacute": '\U000000E1', - "acirc": '\U000000E2', - "acute": '\U000000B4', - "aelig": '\U000000E6', - "agrave": '\U000000E0', - "amp": '\U00000026', - "aring": '\U000000E5', - "atilde": '\U000000E3', - "auml": '\U000000E4', - "brvbar": '\U000000A6', - "ccedil": '\U000000E7', - "cedil": '\U000000B8', - "cent": '\U000000A2', - "copy": '\U000000A9', - "curren": '\U000000A4', - "deg": '\U000000B0', - "divide": '\U000000F7', - "eacute": '\U000000E9', - "ecirc": '\U000000EA', - "egrave": '\U000000E8', - "eth": '\U000000F0', - "euml": '\U000000EB', - "frac12": '\U000000BD', - "frac14": '\U000000BC', - "frac34": '\U000000BE', - "gt": '\U0000003E', - "iacute": '\U000000ED', - "icirc": '\U000000EE', - "iexcl": '\U000000A1', - "igrave": '\U000000EC', - "iquest": '\U000000BF', - "iuml": '\U000000EF', - "laquo": '\U000000AB', - "lt": '\U0000003C', - "macr": '\U000000AF', - "micro": '\U000000B5', - "middot": '\U000000B7', - "nbsp": '\U000000A0', - "not": '\U000000AC', - "ntilde": '\U000000F1', - "oacute": '\U000000F3', - "ocirc": '\U000000F4', - "ograve": '\U000000F2', - "ordf": '\U000000AA', - "ordm": '\U000000BA', - "oslash": '\U000000F8', - "otilde": '\U000000F5', - "ouml": '\U000000F6', - "para": '\U000000B6', - "plusmn": '\U000000B1', - "pound": '\U000000A3', - "quot": '\U00000022', - "raquo": '\U000000BB', - "reg": '\U000000AE', - "sect": '\U000000A7', - "shy": '\U000000AD', - "sup1": '\U000000B9', - "sup2": '\U000000B2', - "sup3": '\U000000B3', - "szlig": '\U000000DF', - "thorn": '\U000000FE', - "times": '\U000000D7', - "uacute": '\U000000FA', - "ucirc": '\U000000FB', - "ugrave": '\U000000F9', - "uml": '\U000000A8', - "uuml": '\U000000FC', - "yacute": '\U000000FD', - "yen": '\U000000A5', - "yuml": '\U000000FF', + "Cross;": '\U00002A2F', + "Cscr;": '\U0001D49E', + "Cup;": '\U000022D3', + "CupCap;": '\U0000224D', + "DD;": '\U00002145', + "DDotrahd;": '\U00002911', + "DJcy;": '\U00000402', + "DScy;": '\U00000405', + "DZcy;": '\U0000040F', + "Dagger;": '\U00002021', + "Darr;": '\U000021A1', + "Dashv;": '\U00002AE4', + "Dcaron;": '\U0000010E', + "Dcy;": '\U00000414', + "Del;": '\U00002207', + "Delta;": '\U00000394', + "Dfr;": '\U0001D507', + "DiacriticalAcute;": '\U000000B4', + "DiacriticalDot;": '\U000002D9', + "DiacriticalDoubleAcute;": '\U000002DD', + "DiacriticalGrave;": '\U00000060', + "DiacriticalTilde;": '\U000002DC', + "Diamond;": '\U000022C4', + "DifferentialD;": '\U00002146', + "Dopf;": '\U0001D53B', + "Dot;": '\U000000A8', + "DotDot;": '\U000020DC', + "DotEqual;": '\U00002250', + "DoubleContourIntegral;": '\U0000222F', + "DoubleDot;": '\U000000A8', + "DoubleDownArrow;": '\U000021D3', + "DoubleLeftArrow;": '\U000021D0', + "DoubleLeftRightArrow;": '\U000021D4', + "DoubleLeftTee;": '\U00002AE4', + "DoubleLongLeftArrow;": '\U000027F8', + "DoubleLongLeftRightArrow;": '\U000027FA', + "DoubleLongRightArrow;": '\U000027F9', + "DoubleRightArrow;": '\U000021D2', + "DoubleRightTee;": '\U000022A8', + "DoubleUpArrow;": '\U000021D1', + "DoubleUpDownArrow;": '\U000021D5', + "DoubleVerticalBar;": '\U00002225', + "DownArrow;": '\U00002193', + "DownArrowBar;": '\U00002913', + "DownArrowUpArrow;": '\U000021F5', + "DownBreve;": '\U00000311', + "DownLeftRightVector;": '\U00002950', + "DownLeftTeeVector;": '\U0000295E', + "DownLeftVector;": '\U000021BD', + "DownLeftVectorBar;": '\U00002956', + "DownRightTeeVector;": '\U0000295F', + "DownRightVector;": '\U000021C1', + "DownRightVectorBar;": '\U00002957', + "DownTee;": '\U000022A4', + "DownTeeArrow;": '\U000021A7', + "Downarrow;": '\U000021D3', + "Dscr;": '\U0001D49F', + "Dstrok;": '\U00000110', + "ENG;": '\U0000014A', + "ETH;": '\U000000D0', + "Eacute;": '\U000000C9', + "Ecaron;": '\U0000011A', + "Ecirc;": '\U000000CA', + "Ecy;": '\U0000042D', + "Edot;": '\U00000116', + "Efr;": '\U0001D508', + "Egrave;": '\U000000C8', + "Element;": '\U00002208', + "Emacr;": '\U00000112', + "EmptySmallSquare;": '\U000025FB', + "EmptyVerySmallSquare;": '\U000025AB', + "Eogon;": '\U00000118', + "Eopf;": '\U0001D53C', + "Epsilon;": '\U00000395', + "Equal;": '\U00002A75', + "EqualTilde;": '\U00002242', + "Equilibrium;": '\U000021CC', + "Escr;": '\U00002130', + "Esim;": '\U00002A73', + "Eta;": '\U00000397', + "Euml;": '\U000000CB', + "Exists;": '\U00002203', + "ExponentialE;": '\U00002147', + "Fcy;": '\U00000424', + "Ffr;": '\U0001D509', + "FilledSmallSquare;": '\U000025FC', + "FilledVerySmallSquare;": '\U000025AA', + "Fopf;": '\U0001D53D', + "ForAll;": '\U00002200', + "Fouriertrf;": '\U00002131', + "Fscr;": '\U00002131', + "GJcy;": '\U00000403', + "GT;": '\U0000003E', + "Gamma;": '\U00000393', + "Gammad;": '\U000003DC', + "Gbreve;": '\U0000011E', + "Gcedil;": '\U00000122', + "Gcirc;": '\U0000011C', + "Gcy;": '\U00000413', + "Gdot;": '\U00000120', + "Gfr;": '\U0001D50A', + "Gg;": '\U000022D9', + "Gopf;": '\U0001D53E', + "GreaterEqual;": '\U00002265', + "GreaterEqualLess;": '\U000022DB', + "GreaterFullEqual;": '\U00002267', + "GreaterGreater;": '\U00002AA2', + "GreaterLess;": '\U00002277', + "GreaterSlantEqual;": '\U00002A7E', + "GreaterTilde;": '\U00002273', + "Gscr;": '\U0001D4A2', + "Gt;": '\U0000226B', + "HARDcy;": '\U0000042A', + "Hacek;": '\U000002C7', + "Hat;": '\U0000005E', + "Hcirc;": '\U00000124', + "Hfr;": '\U0000210C', + "HilbertSpace;": '\U0000210B', + "Hopf;": '\U0000210D', + "HorizontalLine;": '\U00002500', + "Hscr;": '\U0000210B', + "Hstrok;": '\U00000126', + "HumpDownHump;": '\U0000224E', + "HumpEqual;": '\U0000224F', + "IEcy;": '\U00000415', + "IJlig;": '\U00000132', + "IOcy;": '\U00000401', + "Iacute;": '\U000000CD', + "Icirc;": '\U000000CE', + "Icy;": '\U00000418', + "Idot;": '\U00000130', + "Ifr;": '\U00002111', + "Igrave;": '\U000000CC', + "Im;": '\U00002111', + "Imacr;": '\U0000012A', + "ImaginaryI;": '\U00002148', + "Implies;": '\U000021D2', + "Int;": '\U0000222C', + "Integral;": '\U0000222B', + "Intersection;": '\U000022C2', + "InvisibleComma;": '\U00002063', + "InvisibleTimes;": '\U00002062', + "Iogon;": '\U0000012E', + "Iopf;": '\U0001D540', + "Iota;": '\U00000399', + "Iscr;": '\U00002110', + "Itilde;": '\U00000128', + "Iukcy;": '\U00000406', + "Iuml;": '\U000000CF', + "Jcirc;": '\U00000134', + "Jcy;": '\U00000419', + "Jfr;": '\U0001D50D', + "Jopf;": '\U0001D541', + "Jscr;": '\U0001D4A5', + "Jsercy;": '\U00000408', + "Jukcy;": '\U00000404', + "KHcy;": '\U00000425', + "KJcy;": '\U0000040C', + "Kappa;": '\U0000039A', + "Kcedil;": '\U00000136', + "Kcy;": '\U0000041A', + "Kfr;": '\U0001D50E', + "Kopf;": '\U0001D542', + "Kscr;": '\U0001D4A6', + "LJcy;": '\U00000409', + "LT;": '\U0000003C', + "Lacute;": '\U00000139', + "Lambda;": '\U0000039B', + "Lang;": '\U000027EA', + "Laplacetrf;": '\U00002112', + "Larr;": '\U0000219E', + "Lcaron;": '\U0000013D', + "Lcedil;": '\U0000013B', + "Lcy;": '\U0000041B', + "LeftAngleBracket;": '\U000027E8', + "LeftArrow;": '\U00002190', + "LeftArrowBar;": '\U000021E4', + "LeftArrowRightArrow;": '\U000021C6', + "LeftCeiling;": '\U00002308', + "LeftDoubleBracket;": '\U000027E6', + "LeftDownTeeVector;": '\U00002961', + "LeftDownVector;": '\U000021C3', + "LeftDownVectorBar;": '\U00002959', + "LeftFloor;": '\U0000230A', + "LeftRightArrow;": '\U00002194', + "LeftRightVector;": '\U0000294E', + "LeftTee;": '\U000022A3', + "LeftTeeArrow;": '\U000021A4', + "LeftTeeVector;": '\U0000295A', + "LeftTriangle;": '\U000022B2', + "LeftTriangleBar;": '\U000029CF', + "LeftTriangleEqual;": '\U000022B4', + "LeftUpDownVector;": '\U00002951', + "LeftUpTeeVector;": '\U00002960', + "LeftUpVector;": '\U000021BF', + "LeftUpVectorBar;": '\U00002958', + "LeftVector;": '\U000021BC', + "LeftVectorBar;": '\U00002952', + "Leftarrow;": '\U000021D0', + "Leftrightarrow;": '\U000021D4', + "LessEqualGreater;": '\U000022DA', + "LessFullEqual;": '\U00002266', + "LessGreater;": '\U00002276', + "LessLess;": '\U00002AA1', + "LessSlantEqual;": '\U00002A7D', + "LessTilde;": '\U00002272', + "Lfr;": '\U0001D50F', + "Ll;": '\U000022D8', + "Lleftarrow;": '\U000021DA', + "Lmidot;": '\U0000013F', + "LongLeftArrow;": '\U000027F5', + "LongLeftRightArrow;": '\U000027F7', + "LongRightArrow;": '\U000027F6', + "Longleftarrow;": '\U000027F8', + "Longleftrightarrow;": '\U000027FA', + "Longrightarrow;": '\U000027F9', + "Lopf;": '\U0001D543', + "LowerLeftArrow;": '\U00002199', + "LowerRightArrow;": '\U00002198', + "Lscr;": '\U00002112', + "Lsh;": '\U000021B0', + "Lstrok;": '\U00000141', + "Lt;": '\U0000226A', + "Map;": '\U00002905', + "Mcy;": '\U0000041C', + "MediumSpace;": '\U0000205F', + "Mellintrf;": '\U00002133', + "Mfr;": '\U0001D510', + "MinusPlus;": '\U00002213', + "Mopf;": '\U0001D544', + "Mscr;": '\U00002133', + "Mu;": '\U0000039C', + "NJcy;": '\U0000040A', + "Nacute;": '\U00000143', + "Ncaron;": '\U00000147', + "Ncedil;": '\U00000145', + "Ncy;": '\U0000041D', + "NegativeMediumSpace;": '\U0000200B', + "NegativeThickSpace;": '\U0000200B', + "NegativeThinSpace;": '\U0000200B', + "NegativeVeryThinSpace;": '\U0000200B', + "NestedGreaterGreater;": '\U0000226B', + "NestedLessLess;": '\U0000226A', + "NewLine;": '\U0000000A', + "Nfr;": '\U0001D511', + "NoBreak;": '\U00002060', + "NonBreakingSpace;": '\U000000A0', + "Nopf;": '\U00002115', + "Not;": '\U00002AEC', + "NotCongruent;": '\U00002262', + "NotCupCap;": '\U0000226D', + "NotDoubleVerticalBar;": '\U00002226', + "NotElement;": '\U00002209', + "NotEqual;": '\U00002260', + "NotExists;": '\U00002204', + "NotGreater;": '\U0000226F', + "NotGreaterEqual;": '\U00002271', + "NotGreaterLess;": '\U00002279', + "NotGreaterTilde;": '\U00002275', + "NotLeftTriangle;": '\U000022EA', + "NotLeftTriangleEqual;": '\U000022EC', + "NotLess;": '\U0000226E', + "NotLessEqual;": '\U00002270', + "NotLessGreater;": '\U00002278', + "NotLessTilde;": '\U00002274', + "NotPrecedes;": '\U00002280', + "NotPrecedesSlantEqual;": '\U000022E0', + "NotReverseElement;": '\U0000220C', + "NotRightTriangle;": '\U000022EB', + "NotRightTriangleEqual;": '\U000022ED', + "NotSquareSubsetEqual;": '\U000022E2', + "NotSquareSupersetEqual;": '\U000022E3', + "NotSubsetEqual;": '\U00002288', + "NotSucceeds;": '\U00002281', + "NotSucceedsSlantEqual;": '\U000022E1', + "NotSupersetEqual;": '\U00002289', + "NotTilde;": '\U00002241', + "NotTildeEqual;": '\U00002244', + "NotTildeFullEqual;": '\U00002247', + "NotTildeTilde;": '\U00002249', + "NotVerticalBar;": '\U00002224', + "Nscr;": '\U0001D4A9', + "Ntilde;": '\U000000D1', + "Nu;": '\U0000039D', + "OElig;": '\U00000152', + "Oacute;": '\U000000D3', + "Ocirc;": '\U000000D4', + "Ocy;": '\U0000041E', + "Odblac;": '\U00000150', + "Ofr;": '\U0001D512', + "Ograve;": '\U000000D2', + "Omacr;": '\U0000014C', + "Omega;": '\U000003A9', + "Omicron;": '\U0000039F', + "Oopf;": '\U0001D546', + "OpenCurlyDoubleQuote;": '\U0000201C', + "OpenCurlyQuote;": '\U00002018', + "Or;": '\U00002A54', + "Oscr;": '\U0001D4AA', + "Oslash;": '\U000000D8', + "Otilde;": '\U000000D5', + "Otimes;": '\U00002A37', + "Ouml;": '\U000000D6', + "OverBar;": '\U0000203E', + "OverBrace;": '\U000023DE', + "OverBracket;": '\U000023B4', + "OverParenthesis;": '\U000023DC', + "PartialD;": '\U00002202', + "Pcy;": '\U0000041F', + "Pfr;": '\U0001D513', + "Phi;": '\U000003A6', + "Pi;": '\U000003A0', + "PlusMinus;": '\U000000B1', + "Poincareplane;": '\U0000210C', + "Popf;": '\U00002119', + "Pr;": '\U00002ABB', + "Precedes;": '\U0000227A', + "PrecedesEqual;": '\U00002AAF', + "PrecedesSlantEqual;": '\U0000227C', + "PrecedesTilde;": '\U0000227E', + "Prime;": '\U00002033', + "Product;": '\U0000220F', + "Proportion;": '\U00002237', + "Proportional;": '\U0000221D', + "Pscr;": '\U0001D4AB', + "Psi;": '\U000003A8', + "QUOT;": '\U00000022', + "Qfr;": '\U0001D514', + "Qopf;": '\U0000211A', + "Qscr;": '\U0001D4AC', + "RBarr;": '\U00002910', + "REG;": '\U000000AE', + "Racute;": '\U00000154', + "Rang;": '\U000027EB', + "Rarr;": '\U000021A0', + "Rarrtl;": '\U00002916', + "Rcaron;": '\U00000158', + "Rcedil;": '\U00000156', + "Rcy;": '\U00000420', + "Re;": '\U0000211C', + "ReverseElement;": '\U0000220B', + "ReverseEquilibrium;": '\U000021CB', + "ReverseUpEquilibrium;": '\U0000296F', + "Rfr;": '\U0000211C', + "Rho;": '\U000003A1', + "RightAngleBracket;": '\U000027E9', + "RightArrow;": '\U00002192', + "RightArrowBar;": '\U000021E5', + "RightArrowLeftArrow;": '\U000021C4', + "RightCeiling;": '\U00002309', + "RightDoubleBracket;": '\U000027E7', + "RightDownTeeVector;": '\U0000295D', + "RightDownVector;": '\U000021C2', + "RightDownVectorBar;": '\U00002955', + "RightFloor;": '\U0000230B', + "RightTee;": '\U000022A2', + "RightTeeArrow;": '\U000021A6', + "RightTeeVector;": '\U0000295B', + "RightTriangle;": '\U000022B3', + "RightTriangleBar;": '\U000029D0', + "RightTriangleEqual;": '\U000022B5', + "RightUpDownVector;": '\U0000294F', + "RightUpTeeVector;": '\U0000295C', + "RightUpVector;": '\U000021BE', + "RightUpVectorBar;": '\U00002954', + "RightVector;": '\U000021C0', + "RightVectorBar;": '\U00002953', + "Rightarrow;": '\U000021D2', + "Ropf;": '\U0000211D', + "RoundImplies;": '\U00002970', + "Rrightarrow;": '\U000021DB', + "Rscr;": '\U0000211B', + "Rsh;": '\U000021B1', + "RuleDelayed;": '\U000029F4', + "SHCHcy;": '\U00000429', + "SHcy;": '\U00000428', + "SOFTcy;": '\U0000042C', + "Sacute;": '\U0000015A', + "Sc;": '\U00002ABC', + "Scaron;": '\U00000160', + "Scedil;": '\U0000015E', + "Scirc;": '\U0000015C', + "Scy;": '\U00000421', + "Sfr;": '\U0001D516', + "ShortDownArrow;": '\U00002193', + "ShortLeftArrow;": '\U00002190', + "ShortRightArrow;": '\U00002192', + "ShortUpArrow;": '\U00002191', + "Sigma;": '\U000003A3', + "SmallCircle;": '\U00002218', + "Sopf;": '\U0001D54A', + "Sqrt;": '\U0000221A', + "Square;": '\U000025A1', + "SquareIntersection;": '\U00002293', + "SquareSubset;": '\U0000228F', + "SquareSubsetEqual;": '\U00002291', + "SquareSuperset;": '\U00002290', + "SquareSupersetEqual;": '\U00002292', + "SquareUnion;": '\U00002294', + "Sscr;": '\U0001D4AE', + "Star;": '\U000022C6', + "Sub;": '\U000022D0', + "Subset;": '\U000022D0', + "SubsetEqual;": '\U00002286', + "Succeeds;": '\U0000227B', + "SucceedsEqual;": '\U00002AB0', + "SucceedsSlantEqual;": '\U0000227D', + "SucceedsTilde;": '\U0000227F', + "SuchThat;": '\U0000220B', + "Sum;": '\U00002211', + "Sup;": '\U000022D1', + "Superset;": '\U00002283', + "SupersetEqual;": '\U00002287', + "Supset;": '\U000022D1', + "THORN;": '\U000000DE', + "TRADE;": '\U00002122', + "TSHcy;": '\U0000040B', + "TScy;": '\U00000426', + "Tab;": '\U00000009', + "Tau;": '\U000003A4', + "Tcaron;": '\U00000164', + "Tcedil;": '\U00000162', + "Tcy;": '\U00000422', + "Tfr;": '\U0001D517', + "Therefore;": '\U00002234', + "Theta;": '\U00000398', + "ThinSpace;": '\U00002009', + "Tilde;": '\U0000223C', + "TildeEqual;": '\U00002243', + "TildeFullEqual;": '\U00002245', + "TildeTilde;": '\U00002248', + "Topf;": '\U0001D54B', + "TripleDot;": '\U000020DB', + "Tscr;": '\U0001D4AF', + "Tstrok;": '\U00000166', + "Uacute;": '\U000000DA', + "Uarr;": '\U0000219F', + "Uarrocir;": '\U00002949', + "Ubrcy;": '\U0000040E', + "Ubreve;": '\U0000016C', + "Ucirc;": '\U000000DB', + "Ucy;": '\U00000423', + "Udblac;": '\U00000170', + "Ufr;": '\U0001D518', + "Ugrave;": '\U000000D9', + "Umacr;": '\U0000016A', + "UnderBar;": '\U0000005F', + "UnderBrace;": '\U000023DF', + "UnderBracket;": '\U000023B5', + "UnderParenthesis;": '\U000023DD', + "Union;": '\U000022C3', + "UnionPlus;": '\U0000228E', + "Uogon;": '\U00000172', + "Uopf;": '\U0001D54C', + "UpArrow;": '\U00002191', + "UpArrowBar;": '\U00002912', + "UpArrowDownArrow;": '\U000021C5', + "UpDownArrow;": '\U00002195', + "UpEquilibrium;": '\U0000296E', + "UpTee;": '\U000022A5', + "UpTeeArrow;": '\U000021A5', + "Uparrow;": '\U000021D1', + "Updownarrow;": '\U000021D5', + "UpperLeftArrow;": '\U00002196', + "UpperRightArrow;": '\U00002197', + "Upsi;": '\U000003D2', + "Upsilon;": '\U000003A5', + "Uring;": '\U0000016E', + "Uscr;": '\U0001D4B0', + "Utilde;": '\U00000168', + "Uuml;": '\U000000DC', + "VDash;": '\U000022AB', + "Vbar;": '\U00002AEB', + "Vcy;": '\U00000412', + "Vdash;": '\U000022A9', + "Vdashl;": '\U00002AE6', + "Vee;": '\U000022C1', + "Verbar;": '\U00002016', + "Vert;": '\U00002016', + "VerticalBar;": '\U00002223', + "VerticalLine;": '\U0000007C', + "VerticalSeparator;": '\U00002758', + "VerticalTilde;": '\U00002240', + "VeryThinSpace;": '\U0000200A', + "Vfr;": '\U0001D519', + "Vopf;": '\U0001D54D', + "Vscr;": '\U0001D4B1', + "Vvdash;": '\U000022AA', + "Wcirc;": '\U00000174', + "Wedge;": '\U000022C0', + "Wfr;": '\U0001D51A', + "Wopf;": '\U0001D54E', + "Wscr;": '\U0001D4B2', + "Xfr;": '\U0001D51B', + "Xi;": '\U0000039E', + "Xopf;": '\U0001D54F', + "Xscr;": '\U0001D4B3', + "YAcy;": '\U0000042F', + "YIcy;": '\U00000407', + "YUcy;": '\U0000042E', + "Yacute;": '\U000000DD', + "Ycirc;": '\U00000176', + "Ycy;": '\U0000042B', + "Yfr;": '\U0001D51C', + "Yopf;": '\U0001D550', + "Yscr;": '\U0001D4B4', + "Yuml;": '\U00000178', + "ZHcy;": '\U00000416', + "Zacute;": '\U00000179', + "Zcaron;": '\U0000017D', + "Zcy;": '\U00000417', + "Zdot;": '\U0000017B', + "ZeroWidthSpace;": '\U0000200B', + "Zeta;": '\U00000396', + "Zfr;": '\U00002128', + "Zopf;": '\U00002124', + "Zscr;": '\U0001D4B5', + "aacute;": '\U000000E1', + "abreve;": '\U00000103', + "ac;": '\U0000223E', + "acd;": '\U0000223F', + "acirc;": '\U000000E2', + "acute;": '\U000000B4', + "acy;": '\U00000430', + "aelig;": '\U000000E6', + "af;": '\U00002061', + "afr;": '\U0001D51E', + "agrave;": '\U000000E0', + "alefsym;": '\U00002135', + "aleph;": '\U00002135', + "alpha;": '\U000003B1', + "amacr;": '\U00000101', + "amalg;": '\U00002A3F', + "amp;": '\U00000026', + "and;": '\U00002227', + "andand;": '\U00002A55', + "andd;": '\U00002A5C', + "andslope;": '\U00002A58', + "andv;": '\U00002A5A', + "ang;": '\U00002220', + "ange;": '\U000029A4', + "angle;": '\U00002220', + "angmsd;": '\U00002221', + "angmsdaa;": '\U000029A8', + "angmsdab;": '\U000029A9', + "angmsdac;": '\U000029AA', + "angmsdad;": '\U000029AB', + "angmsdae;": '\U000029AC', + "angmsdaf;": '\U000029AD', + "angmsdag;": '\U000029AE', + "angmsdah;": '\U000029AF', + "angrt;": '\U0000221F', + "angrtvb;": '\U000022BE', + "angrtvbd;": '\U0000299D', + "angsph;": '\U00002222', + "angst;": '\U000000C5', + "angzarr;": '\U0000237C', + "aogon;": '\U00000105', + "aopf;": '\U0001D552', + "ap;": '\U00002248', + "apE;": '\U00002A70', + "apacir;": '\U00002A6F', + "ape;": '\U0000224A', + "apid;": '\U0000224B', + "apos;": '\U00000027', + "approx;": '\U00002248', + "approxeq;": '\U0000224A', + "aring;": '\U000000E5', + "ascr;": '\U0001D4B6', + "ast;": '\U0000002A', + "asymp;": '\U00002248', + "asympeq;": '\U0000224D', + "atilde;": '\U000000E3', + "auml;": '\U000000E4', + "awconint;": '\U00002233', + "awint;": '\U00002A11', + "bNot;": '\U00002AED', + "backcong;": '\U0000224C', + "backepsilon;": '\U000003F6', + "backprime;": '\U00002035', + "backsim;": '\U0000223D', + "backsimeq;": '\U000022CD', + "barvee;": '\U000022BD', + "barwed;": '\U00002305', + "barwedge;": '\U00002305', + "bbrk;": '\U000023B5', + "bbrktbrk;": '\U000023B6', + "bcong;": '\U0000224C', + "bcy;": '\U00000431', + "bdquo;": '\U0000201E', + "becaus;": '\U00002235', + "because;": '\U00002235', + "bemptyv;": '\U000029B0', + "bepsi;": '\U000003F6', + "bernou;": '\U0000212C', + "beta;": '\U000003B2', + "beth;": '\U00002136', + "between;": '\U0000226C', + "bfr;": '\U0001D51F', + "bigcap;": '\U000022C2', + "bigcirc;": '\U000025EF', + "bigcup;": '\U000022C3', + "bigodot;": '\U00002A00', + "bigoplus;": '\U00002A01', + "bigotimes;": '\U00002A02', + "bigsqcup;": '\U00002A06', + "bigstar;": '\U00002605', + "bigtriangledown;": '\U000025BD', + "bigtriangleup;": '\U000025B3', + "biguplus;": '\U00002A04', + "bigvee;": '\U000022C1', + "bigwedge;": '\U000022C0', + "bkarow;": '\U0000290D', + "blacklozenge;": '\U000029EB', + "blacksquare;": '\U000025AA', + "blacktriangle;": '\U000025B4', + "blacktriangledown;": '\U000025BE', + "blacktriangleleft;": '\U000025C2', + "blacktriangleright;": '\U000025B8', + "blank;": '\U00002423', + "blk12;": '\U00002592', + "blk14;": '\U00002591', + "blk34;": '\U00002593', + "block;": '\U00002588', + "bnot;": '\U00002310', + "bopf;": '\U0001D553', + "bot;": '\U000022A5', + "bottom;": '\U000022A5', + "bowtie;": '\U000022C8', + "boxDL;": '\U00002557', + "boxDR;": '\U00002554', + "boxDl;": '\U00002556', + "boxDr;": '\U00002553', + "boxH;": '\U00002550', + "boxHD;": '\U00002566', + "boxHU;": '\U00002569', + "boxHd;": '\U00002564', + "boxHu;": '\U00002567', + "boxUL;": '\U0000255D', + "boxUR;": '\U0000255A', + "boxUl;": '\U0000255C', + "boxUr;": '\U00002559', + "boxV;": '\U00002551', + "boxVH;": '\U0000256C', + "boxVL;": '\U00002563', + "boxVR;": '\U00002560', + "boxVh;": '\U0000256B', + "boxVl;": '\U00002562', + "boxVr;": '\U0000255F', + "boxbox;": '\U000029C9', + "boxdL;": '\U00002555', + "boxdR;": '\U00002552', + "boxdl;": '\U00002510', + "boxdr;": '\U0000250C', + "boxh;": '\U00002500', + "boxhD;": '\U00002565', + "boxhU;": '\U00002568', + "boxhd;": '\U0000252C', + "boxhu;": '\U00002534', + "boxminus;": '\U0000229F', + "boxplus;": '\U0000229E', + "boxtimes;": '\U000022A0', + "boxuL;": '\U0000255B', + "boxuR;": '\U00002558', + "boxul;": '\U00002518', + "boxur;": '\U00002514', + "boxv;": '\U00002502', + "boxvH;": '\U0000256A', + "boxvL;": '\U00002561', + "boxvR;": '\U0000255E', + "boxvh;": '\U0000253C', + "boxvl;": '\U00002524', + "boxvr;": '\U0000251C', + "bprime;": '\U00002035', + "breve;": '\U000002D8', + "brvbar;": '\U000000A6', + "bscr;": '\U0001D4B7', + "bsemi;": '\U0000204F', + "bsim;": '\U0000223D', + "bsime;": '\U000022CD', + "bsol;": '\U0000005C', + "bsolb;": '\U000029C5', + "bsolhsub;": '\U000027C8', + "bull;": '\U00002022', + "bullet;": '\U00002022', + "bump;": '\U0000224E', + "bumpE;": '\U00002AAE', + "bumpe;": '\U0000224F', + "bumpeq;": '\U0000224F', + "cacute;": '\U00000107', + "cap;": '\U00002229', + "capand;": '\U00002A44', + "capbrcup;": '\U00002A49', + "capcap;": '\U00002A4B', + "capcup;": '\U00002A47', + "capdot;": '\U00002A40', + "caret;": '\U00002041', + "caron;": '\U000002C7', + "ccaps;": '\U00002A4D', + "ccaron;": '\U0000010D', + "ccedil;": '\U000000E7', + "ccirc;": '\U00000109', + "ccups;": '\U00002A4C', + "ccupssm;": '\U00002A50', + "cdot;": '\U0000010B', + "cedil;": '\U000000B8', + "cemptyv;": '\U000029B2', + "cent;": '\U000000A2', + "centerdot;": '\U000000B7', + "cfr;": '\U0001D520', + "chcy;": '\U00000447', + "check;": '\U00002713', + "checkmark;": '\U00002713', + "chi;": '\U000003C7', + "cir;": '\U000025CB', + "cirE;": '\U000029C3', + "circ;": '\U000002C6', + "circeq;": '\U00002257', + "circlearrowleft;": '\U000021BA', + "circlearrowright;": '\U000021BB', + "circledR;": '\U000000AE', + "circledS;": '\U000024C8', + "circledast;": '\U0000229B', + "circledcirc;": '\U0000229A', + "circleddash;": '\U0000229D', + "cire;": '\U00002257', + "cirfnint;": '\U00002A10', + "cirmid;": '\U00002AEF', + "cirscir;": '\U000029C2', + "clubs;": '\U00002663', + "clubsuit;": '\U00002663', + "colon;": '\U0000003A', + "colone;": '\U00002254', + "coloneq;": '\U00002254', + "comma;": '\U0000002C', + "commat;": '\U00000040', + "comp;": '\U00002201', + "compfn;": '\U00002218', + "complement;": '\U00002201', + "complexes;": '\U00002102', + "cong;": '\U00002245', + "congdot;": '\U00002A6D', + "conint;": '\U0000222E', + "copf;": '\U0001D554', + "coprod;": '\U00002210', + "copy;": '\U000000A9', + "copysr;": '\U00002117', + "crarr;": '\U000021B5', + "cross;": '\U00002717', + "cscr;": '\U0001D4B8', + "csub;": '\U00002ACF', + "csube;": '\U00002AD1', + "csup;": '\U00002AD0', + "csupe;": '\U00002AD2', + "ctdot;": '\U000022EF', + "cudarrl;": '\U00002938', + "cudarrr;": '\U00002935', + "cuepr;": '\U000022DE', + "cuesc;": '\U000022DF', + "cularr;": '\U000021B6', + "cularrp;": '\U0000293D', + "cup;": '\U0000222A', + "cupbrcap;": '\U00002A48', + "cupcap;": '\U00002A46', + "cupcup;": '\U00002A4A', + "cupdot;": '\U0000228D', + "cupor;": '\U00002A45', + "curarr;": '\U000021B7', + "curarrm;": '\U0000293C', + "curlyeqprec;": '\U000022DE', + "curlyeqsucc;": '\U000022DF', + "curlyvee;": '\U000022CE', + "curlywedge;": '\U000022CF', + "curren;": '\U000000A4', + "curvearrowleft;": '\U000021B6', + "curvearrowright;": '\U000021B7', + "cuvee;": '\U000022CE', + "cuwed;": '\U000022CF', + "cwconint;": '\U00002232', + "cwint;": '\U00002231', + "cylcty;": '\U0000232D', + "dArr;": '\U000021D3', + "dHar;": '\U00002965', + "dagger;": '\U00002020', + "daleth;": '\U00002138', + "darr;": '\U00002193', + "dash;": '\U00002010', + "dashv;": '\U000022A3', + "dbkarow;": '\U0000290F', + "dblac;": '\U000002DD', + "dcaron;": '\U0000010F', + "dcy;": '\U00000434', + "dd;": '\U00002146', + "ddagger;": '\U00002021', + "ddarr;": '\U000021CA', + "ddotseq;": '\U00002A77', + "deg;": '\U000000B0', + "delta;": '\U000003B4', + "demptyv;": '\U000029B1', + "dfisht;": '\U0000297F', + "dfr;": '\U0001D521', + "dharl;": '\U000021C3', + "dharr;": '\U000021C2', + "diam;": '\U000022C4', + "diamond;": '\U000022C4', + "diamondsuit;": '\U00002666', + "diams;": '\U00002666', + "die;": '\U000000A8', + "digamma;": '\U000003DD', + "disin;": '\U000022F2', + "div;": '\U000000F7', + "divide;": '\U000000F7', + "divideontimes;": '\U000022C7', + "divonx;": '\U000022C7', + "djcy;": '\U00000452', + "dlcorn;": '\U0000231E', + "dlcrop;": '\U0000230D', + "dollar;": '\U00000024', + "dopf;": '\U0001D555', + "dot;": '\U000002D9', + "doteq;": '\U00002250', + "doteqdot;": '\U00002251', + "dotminus;": '\U00002238', + "dotplus;": '\U00002214', + "dotsquare;": '\U000022A1', + "doublebarwedge;": '\U00002306', + "downarrow;": '\U00002193', + "downdownarrows;": '\U000021CA', + "downharpoonleft;": '\U000021C3', + "downharpoonright;": '\U000021C2', + "drbkarow;": '\U00002910', + "drcorn;": '\U0000231F', + "drcrop;": '\U0000230C', + "dscr;": '\U0001D4B9', + "dscy;": '\U00000455', + "dsol;": '\U000029F6', + "dstrok;": '\U00000111', + "dtdot;": '\U000022F1', + "dtri;": '\U000025BF', + "dtrif;": '\U000025BE', + "duarr;": '\U000021F5', + "duhar;": '\U0000296F', + "dwangle;": '\U000029A6', + "dzcy;": '\U0000045F', + "dzigrarr;": '\U000027FF', + "eDDot;": '\U00002A77', + "eDot;": '\U00002251', + "eacute;": '\U000000E9', + "easter;": '\U00002A6E', + "ecaron;": '\U0000011B', + "ecir;": '\U00002256', + "ecirc;": '\U000000EA', + "ecolon;": '\U00002255', + "ecy;": '\U0000044D', + "edot;": '\U00000117', + "ee;": '\U00002147', + "efDot;": '\U00002252', + "efr;": '\U0001D522', + "eg;": '\U00002A9A', + "egrave;": '\U000000E8', + "egs;": '\U00002A96', + "egsdot;": '\U00002A98', + "el;": '\U00002A99', + "elinters;": '\U000023E7', + "ell;": '\U00002113', + "els;": '\U00002A95', + "elsdot;": '\U00002A97', + "emacr;": '\U00000113', + "empty;": '\U00002205', + "emptyset;": '\U00002205', + "emptyv;": '\U00002205', + "emsp;": '\U00002003', + "emsp13;": '\U00002004', + "emsp14;": '\U00002005', + "eng;": '\U0000014B', + "ensp;": '\U00002002', + "eogon;": '\U00000119', + "eopf;": '\U0001D556', + "epar;": '\U000022D5', + "eparsl;": '\U000029E3', + "eplus;": '\U00002A71', + "epsi;": '\U000003B5', + "epsilon;": '\U000003B5', + "epsiv;": '\U000003F5', + "eqcirc;": '\U00002256', + "eqcolon;": '\U00002255', + "eqsim;": '\U00002242', + "eqslantgtr;": '\U00002A96', + "eqslantless;": '\U00002A95', + "equals;": '\U0000003D', + "equest;": '\U0000225F', + "equiv;": '\U00002261', + "equivDD;": '\U00002A78', + "eqvparsl;": '\U000029E5', + "erDot;": '\U00002253', + "erarr;": '\U00002971', + "escr;": '\U0000212F', + "esdot;": '\U00002250', + "esim;": '\U00002242', + "eta;": '\U000003B7', + "eth;": '\U000000F0', + "euml;": '\U000000EB', + "euro;": '\U000020AC', + "excl;": '\U00000021', + "exist;": '\U00002203', + "expectation;": '\U00002130', + "exponentiale;": '\U00002147', + "fallingdotseq;": '\U00002252', + "fcy;": '\U00000444', + "female;": '\U00002640', + "ffilig;": '\U0000FB03', + "fflig;": '\U0000FB00', + "ffllig;": '\U0000FB04', + "ffr;": '\U0001D523', + "filig;": '\U0000FB01', + "flat;": '\U0000266D', + "fllig;": '\U0000FB02', + "fltns;": '\U000025B1', + "fnof;": '\U00000192', + "fopf;": '\U0001D557', + "forall;": '\U00002200', + "fork;": '\U000022D4', + "forkv;": '\U00002AD9', + "fpartint;": '\U00002A0D', + "frac12;": '\U000000BD', + "frac13;": '\U00002153', + "frac14;": '\U000000BC', + "frac15;": '\U00002155', + "frac16;": '\U00002159', + "frac18;": '\U0000215B', + "frac23;": '\U00002154', + "frac25;": '\U00002156', + "frac34;": '\U000000BE', + "frac35;": '\U00002157', + "frac38;": '\U0000215C', + "frac45;": '\U00002158', + "frac56;": '\U0000215A', + "frac58;": '\U0000215D', + "frac78;": '\U0000215E', + "frasl;": '\U00002044', + "frown;": '\U00002322', + "fscr;": '\U0001D4BB', + "gE;": '\U00002267', + "gEl;": '\U00002A8C', + "gacute;": '\U000001F5', + "gamma;": '\U000003B3', + "gammad;": '\U000003DD', + "gap;": '\U00002A86', + "gbreve;": '\U0000011F', + "gcirc;": '\U0000011D', + "gcy;": '\U00000433', + "gdot;": '\U00000121', + "ge;": '\U00002265', + "gel;": '\U000022DB', + "geq;": '\U00002265', + "geqq;": '\U00002267', + "geqslant;": '\U00002A7E', + "ges;": '\U00002A7E', + "gescc;": '\U00002AA9', + "gesdot;": '\U00002A80', + "gesdoto;": '\U00002A82', + "gesdotol;": '\U00002A84', + "gesles;": '\U00002A94', + "gfr;": '\U0001D524', + "gg;": '\U0000226B', + "ggg;": '\U000022D9', + "gimel;": '\U00002137', + "gjcy;": '\U00000453', + "gl;": '\U00002277', + "glE;": '\U00002A92', + "gla;": '\U00002AA5', + "glj;": '\U00002AA4', + "gnE;": '\U00002269', + "gnap;": '\U00002A8A', + "gnapprox;": '\U00002A8A', + "gne;": '\U00002A88', + "gneq;": '\U00002A88', + "gneqq;": '\U00002269', + "gnsim;": '\U000022E7', + "gopf;": '\U0001D558', + "grave;": '\U00000060', + "gscr;": '\U0000210A', + "gsim;": '\U00002273', + "gsime;": '\U00002A8E', + "gsiml;": '\U00002A90', + "gt;": '\U0000003E', + "gtcc;": '\U00002AA7', + "gtcir;": '\U00002A7A', + "gtdot;": '\U000022D7', + "gtlPar;": '\U00002995', + "gtquest;": '\U00002A7C', + "gtrapprox;": '\U00002A86', + "gtrarr;": '\U00002978', + "gtrdot;": '\U000022D7', + "gtreqless;": '\U000022DB', + "gtreqqless;": '\U00002A8C', + "gtrless;": '\U00002277', + "gtrsim;": '\U00002273', + "hArr;": '\U000021D4', + "hairsp;": '\U0000200A', + "half;": '\U000000BD', + "hamilt;": '\U0000210B', + "hardcy;": '\U0000044A', + "harr;": '\U00002194', + "harrcir;": '\U00002948', + "harrw;": '\U000021AD', + "hbar;": '\U0000210F', + "hcirc;": '\U00000125', + "hearts;": '\U00002665', + "heartsuit;": '\U00002665', + "hellip;": '\U00002026', + "hercon;": '\U000022B9', + "hfr;": '\U0001D525', + "hksearow;": '\U00002925', + "hkswarow;": '\U00002926', + "hoarr;": '\U000021FF', + "homtht;": '\U0000223B', + "hookleftarrow;": '\U000021A9', + "hookrightarrow;": '\U000021AA', + "hopf;": '\U0001D559', + "horbar;": '\U00002015', + "hscr;": '\U0001D4BD', + "hslash;": '\U0000210F', + "hstrok;": '\U00000127', + "hybull;": '\U00002043', + "hyphen;": '\U00002010', + "iacute;": '\U000000ED', + "ic;": '\U00002063', + "icirc;": '\U000000EE', + "icy;": '\U00000438', + "iecy;": '\U00000435', + "iexcl;": '\U000000A1', + "iff;": '\U000021D4', + "ifr;": '\U0001D526', + "igrave;": '\U000000EC', + "ii;": '\U00002148', + "iiiint;": '\U00002A0C', + "iiint;": '\U0000222D', + "iinfin;": '\U000029DC', + "iiota;": '\U00002129', + "ijlig;": '\U00000133', + "imacr;": '\U0000012B', + "image;": '\U00002111', + "imagline;": '\U00002110', + "imagpart;": '\U00002111', + "imath;": '\U00000131', + "imof;": '\U000022B7', + "imped;": '\U000001B5', + "in;": '\U00002208', + "incare;": '\U00002105', + "infin;": '\U0000221E', + "infintie;": '\U000029DD', + "inodot;": '\U00000131', + "int;": '\U0000222B', + "intcal;": '\U000022BA', + "integers;": '\U00002124', + "intercal;": '\U000022BA', + "intlarhk;": '\U00002A17', + "intprod;": '\U00002A3C', + "iocy;": '\U00000451', + "iogon;": '\U0000012F', + "iopf;": '\U0001D55A', + "iota;": '\U000003B9', + "iprod;": '\U00002A3C', + "iquest;": '\U000000BF', + "iscr;": '\U0001D4BE', + "isin;": '\U00002208', + "isinE;": '\U000022F9', + "isindot;": '\U000022F5', + "isins;": '\U000022F4', + "isinsv;": '\U000022F3', + "isinv;": '\U00002208', + "it;": '\U00002062', + "itilde;": '\U00000129', + "iukcy;": '\U00000456', + "iuml;": '\U000000EF', + "jcirc;": '\U00000135', + "jcy;": '\U00000439', + "jfr;": '\U0001D527', + "jmath;": '\U00000237', + "jopf;": '\U0001D55B', + "jscr;": '\U0001D4BF', + "jsercy;": '\U00000458', + "jukcy;": '\U00000454', + "kappa;": '\U000003BA', + "kappav;": '\U000003F0', + "kcedil;": '\U00000137', + "kcy;": '\U0000043A', + "kfr;": '\U0001D528', + "kgreen;": '\U00000138', + "khcy;": '\U00000445', + "kjcy;": '\U0000045C', + "kopf;": '\U0001D55C', + "kscr;": '\U0001D4C0', + "lAarr;": '\U000021DA', + "lArr;": '\U000021D0', + "lAtail;": '\U0000291B', + "lBarr;": '\U0000290E', + "lE;": '\U00002266', + "lEg;": '\U00002A8B', + "lHar;": '\U00002962', + "lacute;": '\U0000013A', + "laemptyv;": '\U000029B4', + "lagran;": '\U00002112', + "lambda;": '\U000003BB', + "lang;": '\U000027E8', + "langd;": '\U00002991', + "langle;": '\U000027E8', + "lap;": '\U00002A85', + "laquo;": '\U000000AB', + "larr;": '\U00002190', + "larrb;": '\U000021E4', + "larrbfs;": '\U0000291F', + "larrfs;": '\U0000291D', + "larrhk;": '\U000021A9', + "larrlp;": '\U000021AB', + "larrpl;": '\U00002939', + "larrsim;": '\U00002973', + "larrtl;": '\U000021A2', + "lat;": '\U00002AAB', + "latail;": '\U00002919', + "late;": '\U00002AAD', + "lbarr;": '\U0000290C', + "lbbrk;": '\U00002772', + "lbrace;": '\U0000007B', + "lbrack;": '\U0000005B', + "lbrke;": '\U0000298B', + "lbrksld;": '\U0000298F', + "lbrkslu;": '\U0000298D', + "lcaron;": '\U0000013E', + "lcedil;": '\U0000013C', + "lceil;": '\U00002308', + "lcub;": '\U0000007B', + "lcy;": '\U0000043B', + "ldca;": '\U00002936', + "ldquo;": '\U0000201C', + "ldquor;": '\U0000201E', + "ldrdhar;": '\U00002967', + "ldrushar;": '\U0000294B', + "ldsh;": '\U000021B2', + "le;": '\U00002264', + "leftarrow;": '\U00002190', + "leftarrowtail;": '\U000021A2', + "leftharpoondown;": '\U000021BD', + "leftharpoonup;": '\U000021BC', + "leftleftarrows;": '\U000021C7', + "leftrightarrow;": '\U00002194', + "leftrightarrows;": '\U000021C6', + "leftrightharpoons;": '\U000021CB', + "leftrightsquigarrow;": '\U000021AD', + "leftthreetimes;": '\U000022CB', + "leg;": '\U000022DA', + "leq;": '\U00002264', + "leqq;": '\U00002266', + "leqslant;": '\U00002A7D', + "les;": '\U00002A7D', + "lescc;": '\U00002AA8', + "lesdot;": '\U00002A7F', + "lesdoto;": '\U00002A81', + "lesdotor;": '\U00002A83', + "lesges;": '\U00002A93', + "lessapprox;": '\U00002A85', + "lessdot;": '\U000022D6', + "lesseqgtr;": '\U000022DA', + "lesseqqgtr;": '\U00002A8B', + "lessgtr;": '\U00002276', + "lesssim;": '\U00002272', + "lfisht;": '\U0000297C', + "lfloor;": '\U0000230A', + "lfr;": '\U0001D529', + "lg;": '\U00002276', + "lgE;": '\U00002A91', + "lhard;": '\U000021BD', + "lharu;": '\U000021BC', + "lharul;": '\U0000296A', + "lhblk;": '\U00002584', + "ljcy;": '\U00000459', + "ll;": '\U0000226A', + "llarr;": '\U000021C7', + "llcorner;": '\U0000231E', + "llhard;": '\U0000296B', + "lltri;": '\U000025FA', + "lmidot;": '\U00000140', + "lmoust;": '\U000023B0', + "lmoustache;": '\U000023B0', + "lnE;": '\U00002268', + "lnap;": '\U00002A89', + "lnapprox;": '\U00002A89', + "lne;": '\U00002A87', + "lneq;": '\U00002A87', + "lneqq;": '\U00002268', + "lnsim;": '\U000022E6', + "loang;": '\U000027EC', + "loarr;": '\U000021FD', + "lobrk;": '\U000027E6', + "longleftarrow;": '\U000027F5', + "longleftrightarrow;": '\U000027F7', + "longmapsto;": '\U000027FC', + "longrightarrow;": '\U000027F6', + "looparrowleft;": '\U000021AB', + "looparrowright;": '\U000021AC', + "lopar;": '\U00002985', + "lopf;": '\U0001D55D', + "loplus;": '\U00002A2D', + "lotimes;": '\U00002A34', + "lowast;": '\U00002217', + "lowbar;": '\U0000005F', + "loz;": '\U000025CA', + "lozenge;": '\U000025CA', + "lozf;": '\U000029EB', + "lpar;": '\U00000028', + "lparlt;": '\U00002993', + "lrarr;": '\U000021C6', + "lrcorner;": '\U0000231F', + "lrhar;": '\U000021CB', + "lrhard;": '\U0000296D', + "lrm;": '\U0000200E', + "lrtri;": '\U000022BF', + "lsaquo;": '\U00002039', + "lscr;": '\U0001D4C1', + "lsh;": '\U000021B0', + "lsim;": '\U00002272', + "lsime;": '\U00002A8D', + "lsimg;": '\U00002A8F', + "lsqb;": '\U0000005B', + "lsquo;": '\U00002018', + "lsquor;": '\U0000201A', + "lstrok;": '\U00000142', + "lt;": '\U0000003C', + "ltcc;": '\U00002AA6', + "ltcir;": '\U00002A79', + "ltdot;": '\U000022D6', + "lthree;": '\U000022CB', + "ltimes;": '\U000022C9', + "ltlarr;": '\U00002976', + "ltquest;": '\U00002A7B', + "ltrPar;": '\U00002996', + "ltri;": '\U000025C3', + "ltrie;": '\U000022B4', + "ltrif;": '\U000025C2', + "lurdshar;": '\U0000294A', + "luruhar;": '\U00002966', + "mDDot;": '\U0000223A', + "macr;": '\U000000AF', + "male;": '\U00002642', + "malt;": '\U00002720', + "maltese;": '\U00002720', + "map;": '\U000021A6', + "mapsto;": '\U000021A6', + "mapstodown;": '\U000021A7', + "mapstoleft;": '\U000021A4', + "mapstoup;": '\U000021A5', + "marker;": '\U000025AE', + "mcomma;": '\U00002A29', + "mcy;": '\U0000043C', + "mdash;": '\U00002014', + "measuredangle;": '\U00002221', + "mfr;": '\U0001D52A', + "mho;": '\U00002127', + "micro;": '\U000000B5', + "mid;": '\U00002223', + "midast;": '\U0000002A', + "midcir;": '\U00002AF0', + "middot;": '\U000000B7', + "minus;": '\U00002212', + "minusb;": '\U0000229F', + "minusd;": '\U00002238', + "minusdu;": '\U00002A2A', + "mlcp;": '\U00002ADB', + "mldr;": '\U00002026', + "mnplus;": '\U00002213', + "models;": '\U000022A7', + "mopf;": '\U0001D55E', + "mp;": '\U00002213', + "mscr;": '\U0001D4C2', + "mstpos;": '\U0000223E', + "mu;": '\U000003BC', + "multimap;": '\U000022B8', + "mumap;": '\U000022B8', + "nLeftarrow;": '\U000021CD', + "nLeftrightarrow;": '\U000021CE', + "nRightarrow;": '\U000021CF', + "nVDash;": '\U000022AF', + "nVdash;": '\U000022AE', + "nabla;": '\U00002207', + "nacute;": '\U00000144', + "nap;": '\U00002249', + "napos;": '\U00000149', + "napprox;": '\U00002249', + "natur;": '\U0000266E', + "natural;": '\U0000266E', + "naturals;": '\U00002115', + "nbsp;": '\U000000A0', + "ncap;": '\U00002A43', + "ncaron;": '\U00000148', + "ncedil;": '\U00000146', + "ncong;": '\U00002247', + "ncup;": '\U00002A42', + "ncy;": '\U0000043D', + "ndash;": '\U00002013', + "ne;": '\U00002260', + "neArr;": '\U000021D7', + "nearhk;": '\U00002924', + "nearr;": '\U00002197', + "nearrow;": '\U00002197', + "nequiv;": '\U00002262', + "nesear;": '\U00002928', + "nexist;": '\U00002204', + "nexists;": '\U00002204', + "nfr;": '\U0001D52B', + "nge;": '\U00002271', + "ngeq;": '\U00002271', + "ngsim;": '\U00002275', + "ngt;": '\U0000226F', + "ngtr;": '\U0000226F', + "nhArr;": '\U000021CE', + "nharr;": '\U000021AE', + "nhpar;": '\U00002AF2', + "ni;": '\U0000220B', + "nis;": '\U000022FC', + "nisd;": '\U000022FA', + "niv;": '\U0000220B', + "njcy;": '\U0000045A', + "nlArr;": '\U000021CD', + "nlarr;": '\U0000219A', + "nldr;": '\U00002025', + "nle;": '\U00002270', + "nleftarrow;": '\U0000219A', + "nleftrightarrow;": '\U000021AE', + "nleq;": '\U00002270', + "nless;": '\U0000226E', + "nlsim;": '\U00002274', + "nlt;": '\U0000226E', + "nltri;": '\U000022EA', + "nltrie;": '\U000022EC', + "nmid;": '\U00002224', + "nopf;": '\U0001D55F', + "not;": '\U000000AC', + "notin;": '\U00002209', + "notinva;": '\U00002209', + "notinvb;": '\U000022F7', + "notinvc;": '\U000022F6', + "notni;": '\U0000220C', + "notniva;": '\U0000220C', + "notnivb;": '\U000022FE', + "notnivc;": '\U000022FD', + "npar;": '\U00002226', + "nparallel;": '\U00002226', + "npolint;": '\U00002A14', + "npr;": '\U00002280', + "nprcue;": '\U000022E0', + "nprec;": '\U00002280', + "nrArr;": '\U000021CF', + "nrarr;": '\U0000219B', + "nrightarrow;": '\U0000219B', + "nrtri;": '\U000022EB', + "nrtrie;": '\U000022ED', + "nsc;": '\U00002281', + "nsccue;": '\U000022E1', + "nscr;": '\U0001D4C3', + "nshortmid;": '\U00002224', + "nshortparallel;": '\U00002226', + "nsim;": '\U00002241', + "nsime;": '\U00002244', + "nsimeq;": '\U00002244', + "nsmid;": '\U00002224', + "nspar;": '\U00002226', + "nsqsube;": '\U000022E2', + "nsqsupe;": '\U000022E3', + "nsub;": '\U00002284', + "nsube;": '\U00002288', + "nsubseteq;": '\U00002288', + "nsucc;": '\U00002281', + "nsup;": '\U00002285', + "nsupe;": '\U00002289', + "nsupseteq;": '\U00002289', + "ntgl;": '\U00002279', + "ntilde;": '\U000000F1', + "ntlg;": '\U00002278', + "ntriangleleft;": '\U000022EA', + "ntrianglelefteq;": '\U000022EC', + "ntriangleright;": '\U000022EB', + "ntrianglerighteq;": '\U000022ED', + "nu;": '\U000003BD', + "num;": '\U00000023', + "numero;": '\U00002116', + "numsp;": '\U00002007', + "nvDash;": '\U000022AD', + "nvHarr;": '\U00002904', + "nvdash;": '\U000022AC', + "nvinfin;": '\U000029DE', + "nvlArr;": '\U00002902', + "nvrArr;": '\U00002903', + "nwArr;": '\U000021D6', + "nwarhk;": '\U00002923', + "nwarr;": '\U00002196', + "nwarrow;": '\U00002196', + "nwnear;": '\U00002927', + "oS;": '\U000024C8', + "oacute;": '\U000000F3', + "oast;": '\U0000229B', + "ocir;": '\U0000229A', + "ocirc;": '\U000000F4', + "ocy;": '\U0000043E', + "odash;": '\U0000229D', + "odblac;": '\U00000151', + "odiv;": '\U00002A38', + "odot;": '\U00002299', + "odsold;": '\U000029BC', + "oelig;": '\U00000153', + "ofcir;": '\U000029BF', + "ofr;": '\U0001D52C', + "ogon;": '\U000002DB', + "ograve;": '\U000000F2', + "ogt;": '\U000029C1', + "ohbar;": '\U000029B5', + "ohm;": '\U000003A9', + "oint;": '\U0000222E', + "olarr;": '\U000021BA', + "olcir;": '\U000029BE', + "olcross;": '\U000029BB', + "oline;": '\U0000203E', + "olt;": '\U000029C0', + "omacr;": '\U0000014D', + "omega;": '\U000003C9', + "omicron;": '\U000003BF', + "omid;": '\U000029B6', + "ominus;": '\U00002296', + "oopf;": '\U0001D560', + "opar;": '\U000029B7', + "operp;": '\U000029B9', + "oplus;": '\U00002295', + "or;": '\U00002228', + "orarr;": '\U000021BB', + "ord;": '\U00002A5D', + "order;": '\U00002134', + "orderof;": '\U00002134', + "ordf;": '\U000000AA', + "ordm;": '\U000000BA', + "origof;": '\U000022B6', + "oror;": '\U00002A56', + "orslope;": '\U00002A57', + "orv;": '\U00002A5B', + "oscr;": '\U00002134', + "oslash;": '\U000000F8', + "osol;": '\U00002298', + "otilde;": '\U000000F5', + "otimes;": '\U00002297', + "otimesas;": '\U00002A36', + "ouml;": '\U000000F6', + "ovbar;": '\U0000233D', + "par;": '\U00002225', + "para;": '\U000000B6', + "parallel;": '\U00002225', + "parsim;": '\U00002AF3', + "parsl;": '\U00002AFD', + "part;": '\U00002202', + "pcy;": '\U0000043F', + "percnt;": '\U00000025', + "period;": '\U0000002E', + "permil;": '\U00002030', + "perp;": '\U000022A5', + "pertenk;": '\U00002031', + "pfr;": '\U0001D52D', + "phi;": '\U000003C6', + "phiv;": '\U000003D5', + "phmmat;": '\U00002133', + "phone;": '\U0000260E', + "pi;": '\U000003C0', + "pitchfork;": '\U000022D4', + "piv;": '\U000003D6', + "planck;": '\U0000210F', + "planckh;": '\U0000210E', + "plankv;": '\U0000210F', + "plus;": '\U0000002B', + "plusacir;": '\U00002A23', + "plusb;": '\U0000229E', + "pluscir;": '\U00002A22', + "plusdo;": '\U00002214', + "plusdu;": '\U00002A25', + "pluse;": '\U00002A72', + "plusmn;": '\U000000B1', + "plussim;": '\U00002A26', + "plustwo;": '\U00002A27', + "pm;": '\U000000B1', + "pointint;": '\U00002A15', + "popf;": '\U0001D561', + "pound;": '\U000000A3', + "pr;": '\U0000227A', + "prE;": '\U00002AB3', + "prap;": '\U00002AB7', + "prcue;": '\U0000227C', + "pre;": '\U00002AAF', + "prec;": '\U0000227A', + "precapprox;": '\U00002AB7', + "preccurlyeq;": '\U0000227C', + "preceq;": '\U00002AAF', + "precnapprox;": '\U00002AB9', + "precneqq;": '\U00002AB5', + "precnsim;": '\U000022E8', + "precsim;": '\U0000227E', + "prime;": '\U00002032', + "primes;": '\U00002119', + "prnE;": '\U00002AB5', + "prnap;": '\U00002AB9', + "prnsim;": '\U000022E8', + "prod;": '\U0000220F', + "profalar;": '\U0000232E', + "profline;": '\U00002312', + "profsurf;": '\U00002313', + "prop;": '\U0000221D', + "propto;": '\U0000221D', + "prsim;": '\U0000227E', + "prurel;": '\U000022B0', + "pscr;": '\U0001D4C5', + "psi;": '\U000003C8', + "puncsp;": '\U00002008', + "qfr;": '\U0001D52E', + "qint;": '\U00002A0C', + "qopf;": '\U0001D562', + "qprime;": '\U00002057', + "qscr;": '\U0001D4C6', + "quaternions;": '\U0000210D', + "quatint;": '\U00002A16', + "quest;": '\U0000003F', + "questeq;": '\U0000225F', + "quot;": '\U00000022', + "rAarr;": '\U000021DB', + "rArr;": '\U000021D2', + "rAtail;": '\U0000291C', + "rBarr;": '\U0000290F', + "rHar;": '\U00002964', + "racute;": '\U00000155', + "radic;": '\U0000221A', + "raemptyv;": '\U000029B3', + "rang;": '\U000027E9', + "rangd;": '\U00002992', + "range;": '\U000029A5', + "rangle;": '\U000027E9', + "raquo;": '\U000000BB', + "rarr;": '\U00002192', + "rarrap;": '\U00002975', + "rarrb;": '\U000021E5', + "rarrbfs;": '\U00002920', + "rarrc;": '\U00002933', + "rarrfs;": '\U0000291E', + "rarrhk;": '\U000021AA', + "rarrlp;": '\U000021AC', + "rarrpl;": '\U00002945', + "rarrsim;": '\U00002974', + "rarrtl;": '\U000021A3', + "rarrw;": '\U0000219D', + "ratail;": '\U0000291A', + "ratio;": '\U00002236', + "rationals;": '\U0000211A', + "rbarr;": '\U0000290D', + "rbbrk;": '\U00002773', + "rbrace;": '\U0000007D', + "rbrack;": '\U0000005D', + "rbrke;": '\U0000298C', + "rbrksld;": '\U0000298E', + "rbrkslu;": '\U00002990', + "rcaron;": '\U00000159', + "rcedil;": '\U00000157', + "rceil;": '\U00002309', + "rcub;": '\U0000007D', + "rcy;": '\U00000440', + "rdca;": '\U00002937', + "rdldhar;": '\U00002969', + "rdquo;": '\U0000201D', + "rdquor;": '\U0000201D', + "rdsh;": '\U000021B3', + "real;": '\U0000211C', + "realine;": '\U0000211B', + "realpart;": '\U0000211C', + "reals;": '\U0000211D', + "rect;": '\U000025AD', + "reg;": '\U000000AE', + "rfisht;": '\U0000297D', + "rfloor;": '\U0000230B', + "rfr;": '\U0001D52F', + "rhard;": '\U000021C1', + "rharu;": '\U000021C0', + "rharul;": '\U0000296C', + "rho;": '\U000003C1', + "rhov;": '\U000003F1', + "rightarrow;": '\U00002192', + "rightarrowtail;": '\U000021A3', + "rightharpoondown;": '\U000021C1', + "rightharpoonup;": '\U000021C0', + "rightleftarrows;": '\U000021C4', + "rightleftharpoons;": '\U000021CC', + "rightrightarrows;": '\U000021C9', + "rightsquigarrow;": '\U0000219D', + "rightthreetimes;": '\U000022CC', + "ring;": '\U000002DA', + "risingdotseq;": '\U00002253', + "rlarr;": '\U000021C4', + "rlhar;": '\U000021CC', + "rlm;": '\U0000200F', + "rmoust;": '\U000023B1', + "rmoustache;": '\U000023B1', + "rnmid;": '\U00002AEE', + "roang;": '\U000027ED', + "roarr;": '\U000021FE', + "robrk;": '\U000027E7', + "ropar;": '\U00002986', + "ropf;": '\U0001D563', + "roplus;": '\U00002A2E', + "rotimes;": '\U00002A35', + "rpar;": '\U00000029', + "rpargt;": '\U00002994', + "rppolint;": '\U00002A12', + "rrarr;": '\U000021C9', + "rsaquo;": '\U0000203A', + "rscr;": '\U0001D4C7', + "rsh;": '\U000021B1', + "rsqb;": '\U0000005D', + "rsquo;": '\U00002019', + "rsquor;": '\U00002019', + "rthree;": '\U000022CC', + "rtimes;": '\U000022CA', + "rtri;": '\U000025B9', + "rtrie;": '\U000022B5', + "rtrif;": '\U000025B8', + "rtriltri;": '\U000029CE', + "ruluhar;": '\U00002968', + "rx;": '\U0000211E', + "sacute;": '\U0000015B', + "sbquo;": '\U0000201A', + "sc;": '\U0000227B', + "scE;": '\U00002AB4', + "scap;": '\U00002AB8', + "scaron;": '\U00000161', + "sccue;": '\U0000227D', + "sce;": '\U00002AB0', + "scedil;": '\U0000015F', + "scirc;": '\U0000015D', + "scnE;": '\U00002AB6', + "scnap;": '\U00002ABA', + "scnsim;": '\U000022E9', + "scpolint;": '\U00002A13', + "scsim;": '\U0000227F', + "scy;": '\U00000441', + "sdot;": '\U000022C5', + "sdotb;": '\U000022A1', + "sdote;": '\U00002A66', + "seArr;": '\U000021D8', + "searhk;": '\U00002925', + "searr;": '\U00002198', + "searrow;": '\U00002198', + "sect;": '\U000000A7', + "semi;": '\U0000003B', + "seswar;": '\U00002929', + "setminus;": '\U00002216', + "setmn;": '\U00002216', + "sext;": '\U00002736', + "sfr;": '\U0001D530', + "sfrown;": '\U00002322', + "sharp;": '\U0000266F', + "shchcy;": '\U00000449', + "shcy;": '\U00000448', + "shortmid;": '\U00002223', + "shortparallel;": '\U00002225', + "shy;": '\U000000AD', + "sigma;": '\U000003C3', + "sigmaf;": '\U000003C2', + "sigmav;": '\U000003C2', + "sim;": '\U0000223C', + "simdot;": '\U00002A6A', + "sime;": '\U00002243', + "simeq;": '\U00002243', + "simg;": '\U00002A9E', + "simgE;": '\U00002AA0', + "siml;": '\U00002A9D', + "simlE;": '\U00002A9F', + "simne;": '\U00002246', + "simplus;": '\U00002A24', + "simrarr;": '\U00002972', + "slarr;": '\U00002190', + "smallsetminus;": '\U00002216', + "smashp;": '\U00002A33', + "smeparsl;": '\U000029E4', + "smid;": '\U00002223', + "smile;": '\U00002323', + "smt;": '\U00002AAA', + "smte;": '\U00002AAC', + "softcy;": '\U0000044C', + "sol;": '\U0000002F', + "solb;": '\U000029C4', + "solbar;": '\U0000233F', + "sopf;": '\U0001D564', + "spades;": '\U00002660', + "spadesuit;": '\U00002660', + "spar;": '\U00002225', + "sqcap;": '\U00002293', + "sqcup;": '\U00002294', + "sqsub;": '\U0000228F', + "sqsube;": '\U00002291', + "sqsubset;": '\U0000228F', + "sqsubseteq;": '\U00002291', + "sqsup;": '\U00002290', + "sqsupe;": '\U00002292', + "sqsupset;": '\U00002290', + "sqsupseteq;": '\U00002292', + "squ;": '\U000025A1', + "square;": '\U000025A1', + "squarf;": '\U000025AA', + "squf;": '\U000025AA', + "srarr;": '\U00002192', + "sscr;": '\U0001D4C8', + "ssetmn;": '\U00002216', + "ssmile;": '\U00002323', + "sstarf;": '\U000022C6', + "star;": '\U00002606', + "starf;": '\U00002605', + "straightepsilon;": '\U000003F5', + "straightphi;": '\U000003D5', + "strns;": '\U000000AF', + "sub;": '\U00002282', + "subE;": '\U00002AC5', + "subdot;": '\U00002ABD', + "sube;": '\U00002286', + "subedot;": '\U00002AC3', + "submult;": '\U00002AC1', + "subnE;": '\U00002ACB', + "subne;": '\U0000228A', + "subplus;": '\U00002ABF', + "subrarr;": '\U00002979', + "subset;": '\U00002282', + "subseteq;": '\U00002286', + "subseteqq;": '\U00002AC5', + "subsetneq;": '\U0000228A', + "subsetneqq;": '\U00002ACB', + "subsim;": '\U00002AC7', + "subsub;": '\U00002AD5', + "subsup;": '\U00002AD3', + "succ;": '\U0000227B', + "succapprox;": '\U00002AB8', + "succcurlyeq;": '\U0000227D', + "succeq;": '\U00002AB0', + "succnapprox;": '\U00002ABA', + "succneqq;": '\U00002AB6', + "succnsim;": '\U000022E9', + "succsim;": '\U0000227F', + "sum;": '\U00002211', + "sung;": '\U0000266A', + "sup;": '\U00002283', + "sup1;": '\U000000B9', + "sup2;": '\U000000B2', + "sup3;": '\U000000B3', + "supE;": '\U00002AC6', + "supdot;": '\U00002ABE', + "supdsub;": '\U00002AD8', + "supe;": '\U00002287', + "supedot;": '\U00002AC4', + "suphsol;": '\U000027C9', + "suphsub;": '\U00002AD7', + "suplarr;": '\U0000297B', + "supmult;": '\U00002AC2', + "supnE;": '\U00002ACC', + "supne;": '\U0000228B', + "supplus;": '\U00002AC0', + "supset;": '\U00002283', + "supseteq;": '\U00002287', + "supseteqq;": '\U00002AC6', + "supsetneq;": '\U0000228B', + "supsetneqq;": '\U00002ACC', + "supsim;": '\U00002AC8', + "supsub;": '\U00002AD4', + "supsup;": '\U00002AD6', + "swArr;": '\U000021D9', + "swarhk;": '\U00002926', + "swarr;": '\U00002199', + "swarrow;": '\U00002199', + "swnwar;": '\U0000292A', + "szlig;": '\U000000DF', + "target;": '\U00002316', + "tau;": '\U000003C4', + "tbrk;": '\U000023B4', + "tcaron;": '\U00000165', + "tcedil;": '\U00000163', + "tcy;": '\U00000442', + "tdot;": '\U000020DB', + "telrec;": '\U00002315', + "tfr;": '\U0001D531', + "there4;": '\U00002234', + "therefore;": '\U00002234', + "theta;": '\U000003B8', + "thetasym;": '\U000003D1', + "thetav;": '\U000003D1', + "thickapprox;": '\U00002248', + "thicksim;": '\U0000223C', + "thinsp;": '\U00002009', + "thkap;": '\U00002248', + "thksim;": '\U0000223C', + "thorn;": '\U000000FE', + "tilde;": '\U000002DC', + "times;": '\U000000D7', + "timesb;": '\U000022A0', + "timesbar;": '\U00002A31', + "timesd;": '\U00002A30', + "tint;": '\U0000222D', + "toea;": '\U00002928', + "top;": '\U000022A4', + "topbot;": '\U00002336', + "topcir;": '\U00002AF1', + "topf;": '\U0001D565', + "topfork;": '\U00002ADA', + "tosa;": '\U00002929', + "tprime;": '\U00002034', + "trade;": '\U00002122', + "triangle;": '\U000025B5', + "triangledown;": '\U000025BF', + "triangleleft;": '\U000025C3', + "trianglelefteq;": '\U000022B4', + "triangleq;": '\U0000225C', + "triangleright;": '\U000025B9', + "trianglerighteq;": '\U000022B5', + "tridot;": '\U000025EC', + "trie;": '\U0000225C', + "triminus;": '\U00002A3A', + "triplus;": '\U00002A39', + "trisb;": '\U000029CD', + "tritime;": '\U00002A3B', + "trpezium;": '\U000023E2', + "tscr;": '\U0001D4C9', + "tscy;": '\U00000446', + "tshcy;": '\U0000045B', + "tstrok;": '\U00000167', + "twixt;": '\U0000226C', + "twoheadleftarrow;": '\U0000219E', + "twoheadrightarrow;": '\U000021A0', + "uArr;": '\U000021D1', + "uHar;": '\U00002963', + "uacute;": '\U000000FA', + "uarr;": '\U00002191', + "ubrcy;": '\U0000045E', + "ubreve;": '\U0000016D', + "ucirc;": '\U000000FB', + "ucy;": '\U00000443', + "udarr;": '\U000021C5', + "udblac;": '\U00000171', + "udhar;": '\U0000296E', + "ufisht;": '\U0000297E', + "ufr;": '\U0001D532', + "ugrave;": '\U000000F9', + "uharl;": '\U000021BF', + "uharr;": '\U000021BE', + "uhblk;": '\U00002580', + "ulcorn;": '\U0000231C', + "ulcorner;": '\U0000231C', + "ulcrop;": '\U0000230F', + "ultri;": '\U000025F8', + "umacr;": '\U0000016B', + "uml;": '\U000000A8', + "uogon;": '\U00000173', + "uopf;": '\U0001D566', + "uparrow;": '\U00002191', + "updownarrow;": '\U00002195', + "upharpoonleft;": '\U000021BF', + "upharpoonright;": '\U000021BE', + "uplus;": '\U0000228E', + "upsi;": '\U000003C5', + "upsih;": '\U000003D2', + "upsilon;": '\U000003C5', + "upuparrows;": '\U000021C8', + "urcorn;": '\U0000231D', + "urcorner;": '\U0000231D', + "urcrop;": '\U0000230E', + "uring;": '\U0000016F', + "urtri;": '\U000025F9', + "uscr;": '\U0001D4CA', + "utdot;": '\U000022F0', + "utilde;": '\U00000169', + "utri;": '\U000025B5', + "utrif;": '\U000025B4', + "uuarr;": '\U000021C8', + "uuml;": '\U000000FC', + "uwangle;": '\U000029A7', + "vArr;": '\U000021D5', + "vBar;": '\U00002AE8', + "vBarv;": '\U00002AE9', + "vDash;": '\U000022A8', + "vangrt;": '\U0000299C', + "varepsilon;": '\U000003F5', + "varkappa;": '\U000003F0', + "varnothing;": '\U00002205', + "varphi;": '\U000003D5', + "varpi;": '\U000003D6', + "varpropto;": '\U0000221D', + "varr;": '\U00002195', + "varrho;": '\U000003F1', + "varsigma;": '\U000003C2', + "vartheta;": '\U000003D1', + "vartriangleleft;": '\U000022B2', + "vartriangleright;": '\U000022B3', + "vcy;": '\U00000432', + "vdash;": '\U000022A2', + "vee;": '\U00002228', + "veebar;": '\U000022BB', + "veeeq;": '\U0000225A', + "vellip;": '\U000022EE', + "verbar;": '\U0000007C', + "vert;": '\U0000007C', + "vfr;": '\U0001D533', + "vltri;": '\U000022B2', + "vopf;": '\U0001D567', + "vprop;": '\U0000221D', + "vrtri;": '\U000022B3', + "vscr;": '\U0001D4CB', + "vzigzag;": '\U0000299A', + "wcirc;": '\U00000175', + "wedbar;": '\U00002A5F', + "wedge;": '\U00002227', + "wedgeq;": '\U00002259', + "weierp;": '\U00002118', + "wfr;": '\U0001D534', + "wopf;": '\U0001D568', + "wp;": '\U00002118', + "wr;": '\U00002240', + "wreath;": '\U00002240', + "wscr;": '\U0001D4CC', + "xcap;": '\U000022C2', + "xcirc;": '\U000025EF', + "xcup;": '\U000022C3', + "xdtri;": '\U000025BD', + "xfr;": '\U0001D535', + "xhArr;": '\U000027FA', + "xharr;": '\U000027F7', + "xi;": '\U000003BE', + "xlArr;": '\U000027F8', + "xlarr;": '\U000027F5', + "xmap;": '\U000027FC', + "xnis;": '\U000022FB', + "xodot;": '\U00002A00', + "xopf;": '\U0001D569', + "xoplus;": '\U00002A01', + "xotime;": '\U00002A02', + "xrArr;": '\U000027F9', + "xrarr;": '\U000027F6', + "xscr;": '\U0001D4CD', + "xsqcup;": '\U00002A06', + "xuplus;": '\U00002A04', + "xutri;": '\U000025B3', + "xvee;": '\U000022C1', + "xwedge;": '\U000022C0', + "yacute;": '\U000000FD', + "yacy;": '\U0000044F', + "ycirc;": '\U00000177', + "ycy;": '\U0000044B', + "yen;": '\U000000A5', + "yfr;": '\U0001D536', + "yicy;": '\U00000457', + "yopf;": '\U0001D56A', + "yscr;": '\U0001D4CE', + "yucy;": '\U0000044E', + "yuml;": '\U000000FF', + "zacute;": '\U0000017A', + "zcaron;": '\U0000017E', + "zcy;": '\U00000437', + "zdot;": '\U0000017C', + "zeetrf;": '\U00002128', + "zeta;": '\U000003B6', + "zfr;": '\U0001D537', + "zhcy;": '\U00000436', + "zigrarr;": '\U000021DD', + "zopf;": '\U0001D56B', + "zscr;": '\U0001D4CF', + "zwj;": '\U0000200D', + "zwnj;": '\U0000200C', + "AElig": '\U000000C6', + "AMP": '\U00000026', + "Aacute": '\U000000C1', + "Acirc": '\U000000C2', + "Agrave": '\U000000C0', + "Aring": '\U000000C5', + "Atilde": '\U000000C3', + "Auml": '\U000000C4', + "COPY": '\U000000A9', + "Ccedil": '\U000000C7', + "ETH": '\U000000D0', + "Eacute": '\U000000C9', + "Ecirc": '\U000000CA', + "Egrave": '\U000000C8', + "Euml": '\U000000CB', + "GT": '\U0000003E', + "Iacute": '\U000000CD', + "Icirc": '\U000000CE', + "Igrave": '\U000000CC', + "Iuml": '\U000000CF', + "LT": '\U0000003C', + "Ntilde": '\U000000D1', + "Oacute": '\U000000D3', + "Ocirc": '\U000000D4', + "Ograve": '\U000000D2', + "Oslash": '\U000000D8', + "Otilde": '\U000000D5', + "Ouml": '\U000000D6', + "QUOT": '\U00000022', + "REG": '\U000000AE', + "THORN": '\U000000DE', + "Uacute": '\U000000DA', + "Ucirc": '\U000000DB', + "Ugrave": '\U000000D9', + "Uuml": '\U000000DC', + "Yacute": '\U000000DD', + "aacute": '\U000000E1', + "acirc": '\U000000E2', + "acute": '\U000000B4', + "aelig": '\U000000E6', + "agrave": '\U000000E0', + "amp": '\U00000026', + "aring": '\U000000E5', + "atilde": '\U000000E3', + "auml": '\U000000E4', + "brvbar": '\U000000A6', + "ccedil": '\U000000E7', + "cedil": '\U000000B8', + "cent": '\U000000A2', + "copy": '\U000000A9', + "curren": '\U000000A4', + "deg": '\U000000B0', + "divide": '\U000000F7', + "eacute": '\U000000E9', + "ecirc": '\U000000EA', + "egrave": '\U000000E8', + "eth": '\U000000F0', + "euml": '\U000000EB', + "frac12": '\U000000BD', + "frac14": '\U000000BC', + "frac34": '\U000000BE', + "gt": '\U0000003E', + "iacute": '\U000000ED', + "icirc": '\U000000EE', + "iexcl": '\U000000A1', + "igrave": '\U000000EC', + "iquest": '\U000000BF', + "iuml": '\U000000EF', + "laquo": '\U000000AB', + "lt": '\U0000003C', + "macr": '\U000000AF', + "micro": '\U000000B5', + "middot": '\U000000B7', + "nbsp": '\U000000A0', + "not": '\U000000AC', + "ntilde": '\U000000F1', + "oacute": '\U000000F3', + "ocirc": '\U000000F4', + "ograve": '\U000000F2', + "ordf": '\U000000AA', + "ordm": '\U000000BA', + "oslash": '\U000000F8', + "otilde": '\U000000F5', + "ouml": '\U000000F6', + "para": '\U000000B6', + "plusmn": '\U000000B1', + "pound": '\U000000A3', + "quot": '\U00000022', + "raquo": '\U000000BB', + "reg": '\U000000AE', + "sect": '\U000000A7', + "shy": '\U000000AD', + "sup1": '\U000000B9', + "sup2": '\U000000B2', + "sup3": '\U000000B3', + "szlig": '\U000000DF', + "thorn": '\U000000FE', + "times": '\U000000D7', + "uacute": '\U000000FA', + "ucirc": '\U000000FB', + "ugrave": '\U000000F9', + "uml": '\U000000A8', + "uuml": '\U000000FC', + "yacute": '\U000000FD', + "yen": '\U000000A5', + "yuml": '\U000000FF', } // HTML entities that are two unicode codepoints. diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/foreign.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/foreign.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/foreign.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/foreign.go 2019-08-17 11:56:26.000000000 +0000 @@ -67,7 +67,7 @@ return false } -// Section 12.2.5.5. +// Section 12.2.6.5. var breakout = map[string]bool{ "b": true, "big": true, @@ -115,7 +115,7 @@ "var": true, } -// Section 12.2.5.5. +// Section 12.2.6.5. var svgTagNameAdjustments = map[string]string{ "altglyph": "altGlyph", "altglyphdef": "altGlyphDef", @@ -155,7 +155,7 @@ "textpath": "textPath", } -// Section 12.2.5.1 +// Section 12.2.6.1 var mathMLAttributeAdjustments = map[string]string{ "definitionurl": "definitionURL", } diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/node.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/node.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/node.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/node.go 2019-08-17 11:56:26.000000000 +0000 @@ -21,9 +21,10 @@ scopeMarkerNode ) -// Section 12.2.3.3 says "scope markers are inserted when entering applet -// elements, buttons, object elements, marquees, table cells, and table -// captions, and are used to prevent formatting from 'leaking'". +// Section 12.2.4.3 says "The markers are inserted when entering applet, +// object, marquee, template, td, th, and caption elements, and are used +// to prevent formatting from "leaking" into applet, object, marquee, +// template, td, th, and caption elements". var scopeMarker = Node{Type: scopeMarkerNode} // A Node consists of a NodeType and some Data (tag name for element nodes, @@ -173,6 +174,16 @@ return -1 } +// contains returns whether a is within s. +func (s *nodeStack) contains(a atom.Atom) bool { + for _, n := range *s { + if n.DataAtom == a && n.Namespace == "" { + return true + } + } + return false +} + // insert inserts a node at the given index. func (s *nodeStack) insert(i int, n *Node) { (*s) = append(*s, nil) @@ -191,3 +202,19 @@ (*s)[j] = nil *s = (*s)[:j] } + +type insertionModeStack []insertionMode + +func (s *insertionModeStack) pop() (im insertionMode) { + i := len(*s) + im = (*s)[i-1] + *s = (*s)[:i-1] + return im +} + +func (s *insertionModeStack) top() insertionMode { + if i := len(*s); i > 0 { + return (*s)[i-1] + } + return nil +} diff -Nru golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/parse.go golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/parse.go --- golang-golang-x-net-dev-0.0+git20180124.0ed95ab+dfsg/html/parse.go 2018-04-03 06:09:03.000000000 +0000 +++ golang-golang-x-net-dev-0.0+git20190811.74dc4d7+dfsg/html/parse.go 2019-08-17 11:56:26.000000000 +0000 @@ -25,20 +25,22 @@ hasSelfClosingToken bool // doc is the document root element. doc *Node - // The stack of open elements (section 12.2.3.2) and active formatting - // elements (section 12.2.3.3). + // The stack of open elements (section 12.2.4.2) and active formatting + // elements (section 12.2.4.3). oe, afe nodeStack - // Element pointers (section 12.2.3.4). + // Element pointers (section 12.2.4.4). head, form *Node - // Other parsing state flags (section 12.2.3.5). + // Other parsing state flags (section 12.2.4.5). scripting, framesetOK bool + // The stack of template insertion modes + templateStack insertionModeStack // im is the current insertion mode. im insertionMode // originalIM is the insertion mode to go back to after completing a text // or inTableText insertion mode. originalIM insertionMode // fosterParenting is whether new elements should be inserted according to - // the foster parenting rules (section 12.2.5.3). + // the foster parenting rules (section 12.2.6.1). fosterParenting bool // quirks is whether the parser is operating in "quirks mode." quirks bool @@ -56,7 +58,7 @@ return p.doc } -// Stop tags for use in popUntil. These come from section 12.2.3.2. +// Stop tags for use in popUntil. These come from section 12.2.4.2. var ( defaultScopeStopTags = map[string][]a.Atom{ "": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template}, @@ -79,7 +81,7 @@ // popUntil pops the stack of open elements at the highest element whose tag // is in matchTags, provided there is no higher element in the scope's stop -// tags (as defined in section 12.2.3.2). It returns whether or not there was +// tags (as defined in section 12.2.4.2). It returns whether or not there was // such an element. If there was not, popUntil leaves the stack unchanged. // // For example, the set of stop tags for table scope is: "html", "table". If @@ -126,7 +128,7 @@ return -1 } case tableScope: - if tagAtom == a.Html || tagAtom == a.Table { + if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template { return -1 } case selectScope: @@ -162,17 +164,17 @@ tagAtom := p.oe[i].DataAtom switch s { case tableScope: - if tagAtom == a.Html || tagAtom == a.Table { + if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template { p.oe = p.oe[:i+1] return } case tableRowScope: - if tagAtom == a.Html || tagAtom == a.Tr { + if tagAtom == a.Html || tagAtom == a.Tr || tagAtom == a.Template { p.oe = p.oe[:i+1] return } case tableBodyScope: - if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead { + if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead || tagAtom == a.Template { p.oe = p.oe[:i+1] return } @@ -183,7 +185,7 @@ } // generateImpliedEndTags pops nodes off the stack of open elements as long as -// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt. +// the top node has a tag name of dd, dt, li, optgroup, option, p, rb, rp, rt or rtc. // If exceptions are specified, nodes with that name will not be popped off. func (p *parser) generateImpliedEndTags(exceptions ...string) { var i int @@ -192,7 +194,7 @@ n := p.oe[i] if n.Type == ElementNode { switch n.DataAtom { - case a.Dd, a.Dt, a.Li, a.Option, a.Optgroup, a.P, a.Rp, a.Rt: + case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc: for _, except := range exceptions { if n.Data == except { break loop @@ -234,9 +236,9 @@ } // fosterParent adds a child node according to the foster parenting rules. -// Section 12.2.5.3, "foster parenting". +// Section 12.2.6.1, "foster parenting". func (p *parser) fosterParent(n *Node) { - var table, parent, prev *Node + var table, parent, prev, template *Node var i int for i = len(p.oe) - 1; i >= 0; i-- { if p.oe[i].DataAtom == a.Table { @@ -245,6 +247,19 @@ } } + var j int + for j = len(p.oe) - 1; j >= 0; j-- { + if p.oe[j].DataAtom == a.Template { + template = p.oe[j] + break + } + } + + if template != nil && (table == nil || j > i) { + template.AppendChild(n) + return + } + if table == nil { // The foster parent is the html element. parent = p.oe[0] @@ -304,7 +319,7 @@ }) } -// Section 12.2.3.3. +// Section 12.2.4.3. func (p *parser) addFormattingElement() { tagAtom, attr := p.tok.DataAtom, p.tok.Attr p.addElement() @@ -351,7 +366,7 @@ p.afe = append(p.afe, p.top()) } -// Section 12.2.3.3. +// Section 12.2.4.3. func (p *parser) clearActiveFormattingElements() { for { n := p.afe.pop() @@ -361,7 +376,7 @@ } } -// Section 12.2.3.3. +// Section 12.2.4.3. func (p *parser) reconstructActiveFormattingElements() { n := p.afe.top() if n == nil { @@ -390,12 +405,12 @@ } } -// Section 12.2.4. +// Section 12.2.5. func (p *parser) acknowledgeSelfClosingTag() { p.hasSelfClosingToken = false } -// An insertion mode (section 12.2.3.1) is the state transition function from +// An insertion mode (section 12.2.4.1) is the state transition function from // a particular state in the HTML5 parser's state machine. It updates the // parser's fields depending on parser.tok (where ErrorToken means EOF). // It returns whether the token was consumed. @@ -403,7 +418,7 @@ // setOriginalIM sets the insertion mode to return to after completing a text or // inTableText insertion mode. -// Section 12.2.3.1, "using the rules for". +// Section 12.2.4.1, "using the rules for". func (p *parser) setOriginalIM() { if p.originalIM != nil { panic("html: bad parser state: originalIM was set twice") @@ -411,18 +426,35 @@ p.originalIM = p.im } -// Section 12.2.3.1, "reset the insertion mode". +// Section 12.2.4.1, "reset the insertion mode". func (p *parser) resetInsertionMode() { for i := len(p.oe) - 1; i >= 0; i-- { n := p.oe[i] - if i == 0 && p.context != nil { + last := i == 0 + if last && p.context != nil { n = p.context } switch n.DataAtom { case a.Select: + if !last { + for ancestor, first := n, p.oe[0]; ancestor != first; { + ancestor = p.oe[p.oe.index(ancestor)-1] + switch ancestor.DataAtom { + case a.Template: + p.im = inSelectIM + return + case a.Table: + p.im = inSelectInTableIM + return + } + } + } p.im = inSelectIM case a.Td, a.Th: + // TODO: remove this divergence from the HTML5 spec. + // + // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668 p.im = inCellIM case a.Tr: p.im = inRowIM @@ -434,25 +466,41 @@ p.im = inColumnGroupIM case a.Table: p.im = inTableIM + case a.Template: + // TODO: remove this divergence from the HTML5 spec. + if n.Namespace != "" { + continue + } + p.im = p.templateStack.top() case a.Head: - p.im = inBodyIM + // TODO: remove this divergence from the HTML5 spec. + // + // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668 + p.im = inHeadIM case a.Body: p.im = inBodyIM case a.Frameset: p.im = inFramesetIM case a.Html: - p.im = beforeHeadIM + if p.head == nil { + p.im = beforeHeadIM + } else { + p.im = afterHeadIM + } default: + if last { + p.im = inBodyIM + return + } continue } return } - p.im = inBodyIM } const whitespace = " \t\r\n\f" -// Section 12.2.5.4.1. +// Section 12.2.6.4.1. func initialIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -479,7 +527,7 @@ return false } -// Section 12.2.5.4.2. +// Section 12.2.6.4.2. func beforeHTMLIM(p *parser) bool { switch p.tok.Type { case DoctypeToken: @@ -517,7 +565,7 @@ return false } -// Section 12.2.5.4.3. +// Section 12.2.6.4.3. func beforeHeadIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -560,7 +608,7 @@ return false } -// Section 12.2.5.4.4. +// Section 12.2.6.4.4. func inHeadIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -582,7 +630,16 @@ p.oe.pop() p.acknowledgeSelfClosingTag() return true - case a.Script, a.Title, a.Noscript, a.Noframes, a.Style: + case a.Noscript: + p.addElement() + if p.scripting { + p.setOriginalIM() + p.im = textIM + } else { + p.im = inHeadNoscriptIM + } + return true + case a.Script, a.Title, a.Noframes, a.Style: p.addElement() p.setOriginalIM() p.im = textIM @@ -590,19 +647,41 @@ case a.Head: // Ignore the token. return true + case a.Template: + p.addElement() + p.afe = append(p.afe, &scopeMarker) + p.framesetOK = false + p.im = inTemplateIM + p.templateStack = append(p.templateStack, inTemplateIM) + return true } case EndTagToken: switch p.tok.DataAtom { case a.Head: - n := p.oe.pop() - if n.DataAtom != a.Head { - panic("html: bad parser state: element not found, in the in-head insertion mode") - } + p.oe.pop() p.im = afterHeadIM return true case a.Body, a.Html, a.Br: p.parseImpliedToken(EndTagToken, a.Head, a.Head.String()) return false + case a.Template: + if !p.oe.contains(a.Template) { + return true + } + // TODO: remove this divergence from the HTML5 spec. + // + // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668 + p.generateImpliedEndTags() + for i := len(p.oe) - 1; i >= 0; i-- { + if n := p.oe[i]; n.Namespace == "" && n.DataAtom == a.Template { + p.oe = p.oe[:i] + break + } + } + p.clearActiveFormattingElements() + p.templateStack.pop() + p.resetInsertionMode() + return true default: // Ignore the token. return true @@ -622,7 +701,50 @@ return false } -// Section 12.2.5.4.6. +// 12.2.6.4.5. +func inHeadNoscriptIM(p *parser) bool { + switch p.tok.Type { + case DoctypeToken: + // Ignore the token. + return true + case StartTagToken: + switch p.tok.DataAtom { + case a.Html: + return inBodyIM(p) + case a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Style: + return inHeadIM(p) + case a.Head, a.Noscript: + // Ignore the token. + return true + } + case EndTagToken: + switch p.tok.DataAtom { + case a.Noscript, a.Br: + default: + // Ignore the token. + return true + } + case TextToken: + s := strings.TrimLeft(p.tok.Data, whitespace) + if len(s) == 0 { + // It was all whitespace. + return inHeadIM(p) + } + case CommentToken: + return inHeadIM(p) + } + p.oe.pop() + if p.top().DataAtom != a.Head { + panic("html: the new current node will be a head element.") + } + p.im = inHeadIM + if p.tok.DataAtom == a.Noscript { + return true + } + return false +} + +// Section 12.2.6.4.6. func afterHeadIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -648,7 +770,7 @@ p.addElement() p.im = inFramesetIM return true - case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title: + case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title: p.oe = append(p.oe, p.head) defer p.oe.remove(p.head) return inHeadIM(p) @@ -660,6 +782,8 @@ switch p.tok.DataAtom { case a.Body, a.Html, a.Br: // Drop down to creating an implied tag. + case a.Template: + return inHeadIM(p) default: // Ignore the token. return true @@ -697,7 +821,7 @@ } } -// Section 12.2.5.4.7. +// Section 12.2.6.4.7. func inBodyIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -727,10 +851,16 @@ case StartTagToken: switch p.tok.DataAtom { case a.Html: + if p.oe.contains(a.Template) { + return true + } copyAttributes(p.oe[0], p.tok) - case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title: + case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title: return inHeadIM(p) case a.Body: + if p.oe.contains(a.Template) { + return true + } if len(p.oe) >= 2 { body := p.oe[1] if body.Type == ElementNode && body.DataAtom == a.Body { @@ -767,9 +897,13 @@ // The newline, if any, will be dealt with by the TextToken case. p.framesetOK = false case a.Form: - if p.form == nil { - p.popUntil(buttonScope, a.P) - p.addElement() + if p.form != nil && !p.oe.contains(a.Template) { + // Ignore the token + return true + } + p.popUntil(buttonScope, a.P) + p.addElement() + if !p.oe.contains(a.Template) { p.form = p.top() } case a.Li: @@ -819,7 +953,7 @@ case a.A: for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- { if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A { - p.inBodyEndTagFormatting(a.A) + p.inBodyEndTagFormatting(a.A, "a") p.oe.remove(n) p.afe.remove(n) break @@ -833,7 +967,7 @@ case a.Nobr: p.reconstructActiveFormattingElements() if p.elementInScope(defaultScope, a.Nobr) { - p.inBodyEndTagFormatting(a.Nobr) + p.inBodyEndTagFormatting(a.Nobr, "nobr") p.reconstructActiveFormattingElements() } p.addFormattingElement() @@ -903,6 +1037,14 @@ p.acknowledgeSelfClosingTag() p.popUntil(buttonScope, a.P) p.parseImpliedToken(StartTagToken, a.Form, a.Form.String()) + if p.form == nil { + // NOTE: The 'isindex' element has been removed, + // and the 'template' element has not been designed to be + // collaborative with the index element. + // + // Ignore the token. + return true + } if action != "" { p.form.Attr = []Attribute{{Key: "action", Val: action}} } @@ -952,11 +1094,16 @@ } p.reconstructActiveFormattingElements() p.addElement() - case a.Rp, a.Rt: + case a.Rb, a.Rtc: if p.elementInScope(defaultScope, a.Ruby) { p.generateImpliedEndTags() } p.addElement() + case a.Rp, a.Rt: + if p.elementInScope(defaultScope, a.Ruby) { + p.generateImpliedEndTags("rtc") + } + p.addElement() case a.Math, a.Svg: p.reconstructActiveFormattingElements() if p.tok.DataAtom == a.Math { @@ -993,15 +1140,29 @@ case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul: p.popUntil(defaultScope, p.tok.DataAtom) case a.Form: - node := p.form - p.form = nil - i := p.indexOfElementInScope(defaultScope, a.Form) - if node == nil || i == -1 || p.oe[i] != node { - // Ignore the token. - return true + if p.oe.contains(a.Template) { + i := p.indexOfElementInScope(defaultScope, a.Form) + if i == -1 { + // Ignore the token. + return true + } + p.generateImpliedEndTags() + if p.oe[i].DataAtom != a.Form { + // Ignore the token. + return true + } + p.popUntil(defaultScope, a.Form) + } else { + node := p.form + p.form = nil + i := p.indexOfElementInScope(defaultScope, a.Form) + if node == nil || i == -1 || p.oe[i] != node { + // Ignore the token. + return true + } + p.generateImpliedEndTags() + p.oe.remove(node) } - p.generateImpliedEndTags() - p.oe.remove(node) case a.P: if !p.elementInScope(buttonScope, a.P) { p.parseImpliedToken(StartTagToken, a.P, a.P.String()) @@ -1014,7 +1175,7 @@ case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6: p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6) case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U: - p.inBodyEndTagFormatting(p.tok.DataAtom) + p.inBodyEndTagFormatting(p.tok.DataAtom, p.tok.Data) case a.Applet, a.Marquee, a.Object: if p.popUntil(defaultScope, p.tok.DataAtom) { p.clearActiveFormattingElements() @@ -1022,20 +1183,37 @@ case a.Br: p.tok.Type = StartTagToken return false + case a.Template: + return inHeadIM(p) default: - p.inBodyEndTagOther(p.tok.DataAtom) + p.inBodyEndTagOther(p.tok.DataAtom, p.tok.Data) } case CommentToken: p.addChild(&Node{ Type: CommentNode, Data: p.tok.Data, }) + case ErrorToken: + // TODO: remove this divergence from the HTML5 spec. + if len(p.templateStack) > 0 { + p.im = inTemplateIM + return false + } else { + for _, e := range p.oe { + switch e.DataAtom { + case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc, a.Tbody, a.Td, a.Tfoot, a.Th, + a.Thead, a.Tr, a.Body, a.Html: + default: + return true + } + } + } } return true } -func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) { +func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) { // This is the "adoption agency" algorithm, described at // https://html.spec.whatwg.org/multipage/syntax.html#adoptionAgency @@ -1057,7 +1235,7 @@ } } if formattingElement == nil { - p.inBodyEndTagOther(tagAtom) + p.inBodyEndTagOther(tagAtom, tagName) return } feIndex := p.oe.index(formattingElement) @@ -1160,11 +1338,19 @@ } // inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM. -// "Any other end tag" handling from 12.2.5.5 The rules for parsing tokens in foreign content +// "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in foreign content // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign -func (p *parser) inBodyEndTagOther(tagAtom a.Atom) { +func (p *parser) inBodyEndTagOther(tagAtom a.Atom, tagName string) { for i := len(p.oe) - 1; i >= 0; i-- { - if p.oe[i].DataAtom == tagAtom { + // Two element nodes have the same tag if they have the same Data (a + // string-typed field). As an optimization, for common HTML tags, each + // Data string is assigned a unique, non-zero DataAtom (a uint32-typed + // field), since integer comparison is faster than string comparison. + // Uncommon (custom) tags get a zero DataAtom. + // + // The if condition here is equivalent to (p.oe[i].Data == tagName). + if (p.oe[i].DataAtom == tagAtom) && + ((tagAtom != 0) || (p.oe[i].Data == tagName)) { p.oe = p.oe[:i] break } @@ -1174,7 +1360,7 @@ } } -// Section 12.2.5.4.8. +// Section 12.2.6.4.8. func textIM(p *parser) bool { switch p.tok.Type { case ErrorToken: @@ -1203,12 +1389,9 @@ return p.tok.Type == EndTagToken } -// Section 12.2.5.4.9. +// Section 12.2.6.4.9. func inTableIM(p *parser) bool { switch p.tok.Type { - case ErrorToken: - // Stop parsing. - return true case TextToken: p.tok.Data = strings.Replace(p.tok.Data, "\x00", "", -1) switch p.oe.top().DataAtom { @@ -1249,7 +1432,7 @@ } // Ignore the token. return true - case a.Style, a.Script: + case a.Style, a.Script, a.Template: return inHeadIM(p) case a.Input: for _, t := range p.tok.Attr { @@ -1261,7 +1444,7 @@ } // Otherwise drop down to the default action. case a.Form: - if p.form != nil { + if p.oe.contains(a.Template) || p.form != nil { // Ignore the token. return true } @@ -1291,6 +1474,8 @@ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr: // Ignore the token. return true + case a.Template: + return inHeadIM(p) } case CommentToken: p.addChild(&Node{ @@ -1301,6 +1486,8 @@ case DoctypeToken: // Ignore the token. return true + case ErrorToken: + return inBodyIM(p) } p.fosterParenting = true @@ -1309,7 +1496,7 @@ return inBodyIM(p) } -// Section 12.2.5.4.11. +// Section 12.2.6.4.11. func inCaptionIM(p *parser) bool { switch p.tok.Type { case StartTagToken: @@ -1355,7 +1542,7 @@ return inBodyIM(p) } -// Section 12.2.5.4.12. +// Section 12.2.6.4.12. func inColumnGroupIM(p *parser) bool { switch p.tok.Type { case TextToken: @@ -1386,11 +1573,13 @@ p.oe.pop() p.acknowledgeSelfClosingTag() return true + case a.Template: + return inHeadIM(p) } case EndTagToken: switch p.tok.DataAtom { case a.Colgroup: - if p.oe.top().DataAtom != a.Html { + if p.oe.top().DataAtom == a.Colgroup { p.oe.pop() p.im = inTableIM } @@ -1398,17 +1587,21 @@ case a.Col: // Ignore the token. return true + case a.Template: + return inHeadIM(p) } + case ErrorToken: + return inBodyIM(p) } - if p.oe.top().DataAtom != a.Html { - p.oe.pop() - p.im = inTableIM - return false + if p.oe.top().DataAtom != a.Colgroup { + return true } - return true + p.oe.pop() + p.im = inTableIM + return false } -// Section 12.2.5.4.13. +// Section 12.2.6.4.13. func inTableBodyIM(p *parser) bool { switch p.tok.Type { case StartTagToken: @@ -1460,7 +1653,7 @@ return inTableIM(p) } -// Section 12.2.5.4.14. +// Section 12.2.6.4.14. func inRowIM(p *parser) bool { switch p.tok.Type { case StartTagToken: @@ -1511,7 +1704,7 @@ return inTableIM(p) } -// Section 12.2.5.4.15. +// Section 12.2.6.4.15. func inCellIM(p *parser) bool { switch p.tok.Type { case StartTagToken: @@ -1551,8 +1744,9 @@ return true } // Close the cell and reprocess. - p.popUntil(tableScope, a.Td, a.Th) - p.clearActiveFormattingElements() + if p.popUntil(tableScope, a.Td, a.Th) { + p.clearActiveFormattingElements() + } p.im = inRowIM return false } @@ -1560,12 +1754,9 @@ return inBodyIM(p) } -// Section 12.2.5.4.16. +// Section 12.2.6.4.16. func inSelectIM(p *parser) bool { switch p.tok.Type { - case ErrorToken: - // Stop parsing. - return true case TextToken: p.addText(strings.Replace(p.tok.Data, "\x00", "", -1)) case StartTagToken: @@ -1586,8 +1777,12 @@ } p.addElement() case a.Select: - p.tok.Type = EndTagToken - return false + if p.popUntil(selectScope, a.Select) { + p.resetInsertionMode() + } else { + // Ignore the token. + return true + } case a.Input, a.Keygen, a.Textarea: if p.elementInScope(selectScope, a.Select) { p.parseImpliedToken(EndTagToken, a.Select, a.Select.String()) @@ -1597,7 +1792,7 @@ p.tokenizer.NextIsNotRawText() // Ignore the token. return true - case a.Script: + case a.Script, a.Template: return inHeadIM(p) } case EndTagToken: @@ -1617,7 +1812,12 @@ case a.Select: if p.popUntil(selectScope, a.Select) { p.resetInsertionMode() + } else { + // Ignore the token. + return true } + case a.Template: + return inHeadIM(p) } case CommentToken: p.addChild(&Node{ @@ -1627,30 +1827,107 @@ case DoctypeToken: // Ignore the token. return true + case ErrorToken: + return inBodyIM(p) } return true } -// Section 12.2.5.4.17. +// Section 12.2.6.4.17. func inSelectInTableIM(p *parser) bool { switch p.tok.Type { case StartTagToken, EndTagToken: switch p.tok.DataAtom { case a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th: - if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.DataAtom) { - p.parseImpliedToken(EndTagToken, a.Select, a.Select.String()) - return false - } else { + if p.tok.Type == EndTagToken && !p.elementInScope(tableScope, p.tok.DataAtom) { // Ignore the token. return true } + // This is like p.popUntil(selectScope, a.Select), but it also + // matches , not just

` + want := `| +| +|