github.com/ergo-services/ergo@v1.999.224/etf/decode.go (about) 1 package etf 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "math" 7 "math/big" 8 "reflect" 9 10 "github.com/ergo-services/ergo/lib" 11 ) 12 13 // linked list for decoding complex types like list/map/tuple 14 type stackElement struct { 15 parent *stackElement 16 reg *reflect.Value // used for registered types decoding 17 term Term //value 18 tmp Term // temporary value. used as a temporary storage for a key of map 19 i int // current 20 children int 21 termType byte 22 23 regKeyKind reflect.Kind // we should align key and value types for maps (int*, float*) 24 regValueKind reflect.Kind // in case of decoding into value with registered type 25 26 strict bool // if encoding/decoding registered types must be strict 27 } 28 29 var ( 30 biggestInt = big.NewInt(0xfffffffffffffff) 31 lowestInt = big.NewInt(-0xfffffffffffffff) 32 33 termNil = make(List, 0) 34 35 errMalformedAtomUTF8 = fmt.Errorf("Malformed ETF. ettAtomUTF8") 36 errMalformedSmallAtomUTF8 = fmt.Errorf("Malformed ETF. ettSmallAtomUTF8") 37 errMalformedString = fmt.Errorf("Malformed ETF. ettString") 38 errMalformedCacheRef = fmt.Errorf("Malformed ETF. ettCacheRef") 39 errMalformedNewFloat = fmt.Errorf("Malformed ETF. ettNewFloat") 40 errMalformedFloat = fmt.Errorf("Malformed ETF. ettFloat") 41 errMalformedSmallInteger = fmt.Errorf("Malformed ETF. ettSmallInteger") 42 errMalformedInteger = fmt.Errorf("Malformed ETF. ettInteger") 43 errMalformedSmallBig = fmt.Errorf("Malformed ETF. ettSmallBig") 44 errMalformedLargeBig = fmt.Errorf("Malformed ETF. ettLargeBig") 45 errMalformedList = fmt.Errorf("Malformed ETF. ettList") 46 errMalformedSmallTuple = fmt.Errorf("Malformed ETF. ettSmallTuple") 47 errMalformedLargeTuple = fmt.Errorf("Malformed ETF. ettLargeTuple") 48 errMalformedMap = fmt.Errorf("Malformed ETF. ettMap") 49 errMalformedBinary = fmt.Errorf("Malformed ETF. ettBinary") 50 errMalformedBitBinary = fmt.Errorf("Malformed ETF. ettBitBinary") 51 errMalformedPid = fmt.Errorf("Malformed ETF. ettPid") 52 errMalformedNewPid = fmt.Errorf("Malformed ETF. ettNewPid") 53 errMalformedRef = fmt.Errorf("Malformed ETF. ettNewRef") 54 errMalformedNewRef = fmt.Errorf("Malformed ETF. ettNewerRef") 55 errMalformedPort = fmt.Errorf("Malformed ETF. ettPort") 56 errMalformedNewPort = fmt.Errorf("Malformed ETF. ettNewPort") 57 errMalformedFun = fmt.Errorf("Malformed ETF. ettNewFun") 58 errMalformedExport = fmt.Errorf("Malformed ETF. ettExport") 59 errMalformedUnknownType = fmt.Errorf("Malformed ETF. unknown type") 60 61 errMalformed = fmt.Errorf("Malformed ETF") 62 errInternal = fmt.Errorf("Internal error") 63 ) 64 65 // DecodeOptions 66 type DecodeOptions struct { 67 AtomMapping *AtomMapping 68 FlagBigPidRef bool 69 } 70 71 // stackless implementation is speeding up decoding function up to x25 times 72 73 // it might looks hard to understand the logic, but 74 // there are only two stages 75 // 1) Stage1: decoding basic types (atoms, strings, numbers...) 76 // 2) Stage2: decoding list/tuples/maps and complex types like Port/Pid/Ref using linked list named 'stack' 77 // 78 // see comments within this function 79 80 // Decode 81 func Decode(packet []byte, cache []Atom, options DecodeOptions) (retTerm Term, retByte []byte, retErr error) { 82 var term Term 83 var stack *stackElement 84 var child *stackElement 85 var t byte 86 if lib.CatchPanic() { 87 defer func() { 88 // We should catch any panic happened during decoding the raw data. 89 // Some of the Erlang' types can not be supported in Golang. 90 // As an example: Erlang map with tuple as a key cause a panic 91 // in Golang runtime with message: 92 // 'panic: runtime error: hash of unhashable type etf.Tuple' 93 // The problem is in etf.Tuple type - it is interface type. At the same 94 // time Golang does support hashable key in map (like struct as a key), 95 // but it should be known implicitly. It means we can encode such kind 96 // of data, but can not to decode it back. 97 if r := recover(); r != nil { 98 retTerm = nil 99 retByte = nil 100 retErr = fmt.Errorf("%v", r) 101 } 102 }() 103 } 104 105 for { 106 child = nil 107 if len(packet) == 0 { 108 return nil, nil, errMalformed 109 } 110 111 t = packet[0] 112 packet = packet[1:] 113 114 // Stage 1: decoding base type. if have encountered List/Map/Tuple 115 // or complex type like Pid/Ref/Port: 116 // save the state in stackElement and push it to the stack (basically, 117 // we just append the new item to the linked list) 118 // 119 120 switch t { 121 case ettAtomUTF8, ettAtom: 122 if len(packet) < 2 { 123 return nil, nil, errMalformedAtomUTF8 124 } 125 126 n := binary.BigEndian.Uint16(packet) 127 if len(packet) < int(n+2) { 128 return nil, nil, errMalformedAtomUTF8 129 } 130 131 atom := Atom(packet[2 : n+2]) 132 if len([]rune(atom)) > 255 { 133 return nil, nil, errMalformedAtomUTF8 134 } 135 136 // replace atom value if we have mapped value for it 137 if options.AtomMapping != nil { 138 options.AtomMapping.MutexIn.RLock() 139 if mapped, ok := options.AtomMapping.In[atom]; ok { 140 atom = mapped 141 } 142 options.AtomMapping.MutexIn.RUnlock() 143 } 144 145 term = atom 146 packet = packet[n+2:] 147 148 case ettSmallAtomUTF8, ettSmallAtom: 149 if len(packet) == 0 { 150 return nil, nil, errMalformedSmallAtomUTF8 151 } 152 153 n := int(packet[0]) 154 if len(packet) < n+1 { 155 return nil, nil, errMalformedSmallAtomUTF8 156 } 157 158 switch Atom(packet[1 : n+1]) { 159 case "true": 160 term = true 161 case "false": 162 term = false 163 default: 164 atom := Atom(packet[1 : n+1]) 165 // replace atom value if we have mapped value for it 166 if options.AtomMapping != nil { 167 options.AtomMapping.MutexIn.RLock() 168 if mapped, ok := options.AtomMapping.In[atom]; ok { 169 atom = mapped 170 } 171 options.AtomMapping.MutexIn.RUnlock() 172 } 173 term = atom 174 } 175 packet = packet[n+1:] 176 177 case ettString: 178 if len(packet) < 2 { 179 return nil, nil, errMalformedString 180 } 181 182 n := binary.BigEndian.Uint16(packet) 183 if len(packet) < int(n+2) { 184 return nil, nil, errMalformedString 185 } 186 187 term = string(packet[2 : n+2]) 188 packet = packet[n+2:] 189 190 case ettCacheRef: 191 if len(packet) == 0 { 192 return nil, nil, errMalformedCacheRef 193 } 194 195 switch cache[int(packet[0])] { 196 case "true": 197 term = true 198 case "false": 199 term = false 200 default: 201 atom := cache[int(packet[0])] 202 // replace atom value if we have mapped value for it 203 if options.AtomMapping != nil { 204 options.AtomMapping.MutexIn.RLock() 205 if mapped, ok := options.AtomMapping.In[atom]; ok { 206 atom = mapped 207 } 208 options.AtomMapping.MutexIn.RUnlock() 209 } 210 term = atom 211 } 212 packet = packet[1:] 213 214 case ettSmallInteger: 215 if len(packet) == 0 { 216 return nil, nil, errMalformedSmallInteger 217 } 218 219 i := int(packet[0]) 220 term = int(i) 221 packet = packet[1:] 222 223 if stack == nil { 224 break 225 } 226 227 t := stack.regKeyKind 228 if stack.i&0x01 == 1 { 229 t = stack.regValueKind 230 } 231 switch t { 232 case reflect.Invalid: 233 // not registered type 234 break 235 case reflect.Int64: 236 term = int64(i) 237 case reflect.Int: 238 term = i 239 case reflect.Int8: 240 if i > math.MaxInt8 || i < math.MinInt8 { 241 panic("overflows int8") 242 } 243 term = int8(i) 244 case reflect.Int16: 245 term = int16(i) 246 case reflect.Int32: 247 term = int32(i) 248 case reflect.Uint: 249 term = uint(i) 250 case reflect.Uint8: 251 term = uint8(i) 252 case reflect.Uint16: 253 term = uint16(i) 254 case reflect.Uint32: 255 term = uint32(i) 256 default: 257 panic("destination value is not an int* or overflows") 258 } 259 260 case ettInteger: 261 if len(packet) < 4 { 262 return nil, nil, errMalformedInteger 263 } 264 265 // negatives are encoded as ettSmallBig so the value shouldn't be 266 // greater int32 267 i := int32(binary.BigEndian.Uint32(packet[:4])) 268 term = int64(i) 269 packet = packet[4:] 270 271 if stack == nil { 272 break 273 } 274 275 t := stack.regKeyKind 276 if stack.i&0x01 == 1 { 277 t = stack.regValueKind 278 } 279 switch t { 280 case reflect.Invalid: 281 // not registered type 282 break 283 case reflect.Int64: 284 term = int64(i) 285 case reflect.Int: 286 term = int(i) 287 case reflect.Int8: 288 if i > math.MaxInt8 || i < math.MinInt8 { 289 panic("overflows int8") 290 } 291 term = int8(i) 292 case reflect.Int16: 293 if i > math.MaxInt16 || i < math.MinInt16 { 294 panic("overflows int16") 295 } 296 term = int16(i) 297 case reflect.Int32: 298 term = i 299 case reflect.Uint: 300 term = uint(i) 301 case reflect.Uint8: 302 if i > math.MaxUint8 { 303 panic("overflows uint") 304 } 305 term = uint8(i) 306 case reflect.Uint16: 307 if i > math.MaxUint16 { 308 panic("overflows uint") 309 } 310 term = uint16(i) 311 case reflect.Uint32: 312 term = uint32(i) 313 default: 314 panic("destination value is not an int* or overflows") 315 } 316 317 case ettSmallBig: 318 if len(packet) == 0 { 319 return nil, nil, errMalformedSmallBig 320 } 321 322 n := packet[0] 323 negative := packet[1] == 1 // sign 324 325 ///// this block improves performance at least 4 times 326 if n < 9 { // treat as an int64/uint64 327 le8 := make([]byte, 8) 328 copy(le8, packet[2:n+2]) 329 smallBig := binary.LittleEndian.Uint64(le8) 330 if negative { 331 term = int64(-smallBig) 332 } else { 333 if smallBig > math.MaxInt64 { 334 term = uint64(smallBig) 335 } else { 336 term = int64(smallBig) 337 } 338 } 339 packet = packet[n+2:] 340 341 if stack == nil { 342 break 343 } 344 345 t := stack.regKeyKind 346 if stack.i&0x01 == 1 { 347 t = stack.regValueKind 348 } 349 switch t { 350 case reflect.Invalid: 351 // not registered type 352 break 353 case reflect.Int64: 354 if negative { 355 if smallBig > -math.MinInt64 { 356 panic("overflows int64") 357 } 358 term = int64(-smallBig) 359 } else { 360 if smallBig > math.MaxInt64 { 361 panic("overflows int64") 362 } 363 term = int64(smallBig) 364 } 365 case reflect.Int: 366 if negative { 367 if smallBig > -math.MinInt { 368 panic("overflows int") 369 } 370 term = int(-smallBig) 371 } else { 372 if smallBig > math.MaxInt { 373 panic("overflows int") 374 } 375 term = int(smallBig) 376 } 377 case reflect.Int8: 378 if negative { 379 if smallBig > -math.MinInt8 { 380 panic("overflows int8") 381 } 382 term = int8(-smallBig) 383 } else { 384 if smallBig > math.MaxInt8 { 385 panic("overflows int8") 386 } 387 term = int8(smallBig) 388 } 389 case reflect.Int16: 390 if negative { 391 if smallBig > -math.MinInt16 { 392 panic("overflows int16") 393 } 394 term = int16(-smallBig) 395 } else { 396 if smallBig > math.MaxInt16 { 397 panic("overflows int16") 398 } 399 term = int16(smallBig) 400 } 401 case reflect.Int32: 402 if negative { 403 if smallBig > -math.MinInt32 { 404 panic("overflows int32") 405 } 406 term = int32(-smallBig) 407 } else { 408 if smallBig > math.MaxInt32 { 409 panic("overflows int32") 410 } 411 term = int32(smallBig) 412 } 413 case reflect.Uint: 414 if negative { 415 panic("signed integer value") 416 } 417 if smallBig > math.MaxUint { 418 panic("overflows uint") 419 } 420 term = uint(smallBig) 421 case reflect.Uint8: 422 if negative { 423 panic("signed integer value") 424 } 425 if smallBig > math.MaxUint8 { 426 panic("overflows uint8") 427 } 428 term = uint8(smallBig) 429 case reflect.Uint16: 430 if negative { 431 panic("signed integer value") 432 } 433 if smallBig > math.MaxUint16 { 434 panic("overflows uint16") 435 } 436 term = uint16(smallBig) 437 case reflect.Uint32: 438 if negative { 439 panic("signed integer value") 440 } 441 if smallBig > math.MaxUint32 { 442 panic("overflows uint32") 443 } 444 term = uint32(smallBig) 445 default: 446 panic("destination value is not an int* or overflows") 447 } 448 449 break 450 } 451 ///// 452 453 if len(packet) < int(n+2) { 454 return nil, nil, errMalformedSmallBig 455 } 456 bytes := packet[2 : n+2] 457 458 // encoded as a little endian. convert it to the big endian order 459 l := len(bytes) 460 for i := 0; i < l/2; i++ { 461 bytes[i], bytes[l-1-i] = bytes[l-1-i], bytes[i] 462 } 463 464 bigInt := &big.Int{} 465 bigInt.SetBytes(bytes) 466 if negative { 467 bigInt = bigInt.Neg(bigInt) 468 } 469 470 // try int and int64 471 if bigInt.Cmp(biggestInt) < 0 && bigInt.Cmp(lowestInt) > 0 { 472 term = bigInt.Int64() 473 packet = packet[n+2:] 474 break 475 } 476 477 term = bigInt 478 packet = packet[n+2:] 479 480 case ettLargeBig: 481 if len(packet) < 256 { // must be longer than ettSmallBig 482 return nil, nil, errMalformedLargeBig 483 } 484 485 n := binary.BigEndian.Uint32(packet[:4]) 486 negative := packet[4] == 1 // sign 487 488 if len(packet) < int(n+5) { 489 return nil, nil, errMalformedLargeBig 490 } 491 bytes := packet[5 : n+5] 492 493 // encoded as a little endian. convert it to the big endian order 494 l := len(bytes) 495 for i := 0; i < l/2; i++ { 496 bytes[i], bytes[l-1-i] = bytes[l-1-i], bytes[i] 497 } 498 499 bigInt := &big.Int{} 500 bigInt.SetBytes(bytes) 501 if negative { 502 bigInt = bigInt.Neg(bigInt) 503 } 504 505 term = bigInt 506 packet = packet[n+5:] 507 508 case ettList: 509 if len(packet) < 4 { 510 return nil, nil, errMalformedList 511 } 512 513 n := binary.BigEndian.Uint32(packet[:4]) 514 if n == 0 { 515 // must be encoded as ettNil 516 return nil, nil, errMalformedList 517 } 518 519 term = make(List, n+1) 520 packet = packet[4:] 521 child = &stackElement{ 522 parent: stack, 523 termType: ettList, 524 term: term, 525 children: int(n + 1), 526 } 527 528 case ettSmallTuple: 529 if len(packet) == 0 { 530 return nil, nil, errMalformedSmallTuple 531 } 532 533 n := packet[0] 534 packet = packet[1:] 535 term = make(Tuple, n) 536 537 if n == 0 { 538 break 539 } 540 541 child = &stackElement{ 542 parent: stack, 543 termType: ettSmallTuple, 544 term: term, 545 children: int(n), 546 } 547 548 case ettLargeTuple: 549 if len(packet) < 4 { 550 return nil, nil, errMalformedLargeTuple 551 } 552 553 n := binary.BigEndian.Uint32(packet[:4]) 554 packet = packet[4:] 555 term = make(Tuple, n) 556 557 if n == 0 { 558 break 559 } 560 561 child = &stackElement{ 562 parent: stack, 563 termType: ettLargeTuple, 564 term: term, 565 children: int(n), 566 } 567 568 case ettMap: 569 if len(packet) < 4 { 570 return nil, nil, errMalformedMap 571 } 572 573 n := binary.BigEndian.Uint32(packet[:4]) 574 packet = packet[4:] 575 term = make(Map) 576 577 if n == 0 { 578 break 579 } 580 581 child = &stackElement{ 582 parent: stack, 583 termType: ettMap, 584 term: term, 585 children: int(n) * 2, 586 } 587 588 case ettBinary: 589 if len(packet) < 4 { 590 return nil, nil, errMalformedBinary 591 } 592 593 n := binary.BigEndian.Uint32(packet) 594 if len(packet) < int(n+4) { 595 return nil, nil, errMalformedBinary 596 } 597 598 b := make([]byte, n) 599 copy(b, packet[4:n+4]) 600 601 term = b 602 packet = packet[n+4:] 603 604 case ettNil: 605 // for registered types we should use a nil value 606 // otherwise - treat it as an empty list 607 if stack.reg != nil { 608 term = nil 609 } else { 610 term = termNil 611 } 612 613 case ettPid, ettNewPid: 614 child = &stackElement{ 615 parent: stack, 616 termType: t, 617 children: 1, 618 } 619 620 case ettNewRef, ettNewerRef: 621 if len(packet) < 2 { 622 return nil, nil, errMalformedRef 623 } 624 625 l := binary.BigEndian.Uint16(packet[:2]) 626 packet = packet[2:] 627 628 child = &stackElement{ 629 parent: stack, 630 termType: t, 631 children: 1, 632 tmp: l, // save length in temporary place of the stack element 633 } 634 635 case ettExport: 636 child = &stackElement{ 637 parent: stack, 638 termType: t, 639 term: Export{}, 640 children: 3, 641 } 642 643 case ettNewFun: 644 var unique [16]byte 645 646 if len(packet) < 32 { 647 return nil, nil, errMalformedFun 648 } 649 650 copy(unique[:], packet[5:21]) 651 l := binary.BigEndian.Uint32(packet[25:29]) 652 653 fun := Function{ 654 Arity: packet[4], 655 Unique: unique, 656 Index: binary.BigEndian.Uint32(packet[21:25]), 657 FreeVars: make([]Term, l), 658 } 659 660 child = &stackElement{ 661 parent: stack, 662 termType: t, 663 term: fun, 664 children: 4 + int(l), 665 } 666 packet = packet[29:] 667 668 case ettPort, ettNewPort: 669 child = &stackElement{ 670 parent: stack, 671 termType: t, 672 children: 1, 673 } 674 675 case ettBitBinary: 676 if len(packet) < 6 { 677 return nil, nil, errMalformedBitBinary 678 } 679 680 n := binary.BigEndian.Uint32(packet) 681 bits := uint(packet[4]) 682 683 b := make([]byte, n) 684 copy(b, packet[5:n+5]) 685 b[n-1] = b[n-1] >> (8 - bits) 686 687 term = b 688 packet = packet[n+5:] 689 690 case ettNewFloat: 691 if len(packet) < 8 { 692 return nil, nil, errMalformedNewFloat 693 } 694 bits := binary.BigEndian.Uint64(packet[:8]) 695 696 f := math.Float64frombits(bits) 697 term = f 698 packet = packet[8:] 699 700 if stack == nil { 701 break 702 } 703 704 t := stack.regKeyKind 705 if stack.i&0x01 == 1 { 706 t = stack.regValueKind 707 } 708 switch t { 709 case reflect.Invalid: 710 // not registered type 711 break 712 case reflect.Float64: 713 break 714 case reflect.Float32: 715 if f > math.MaxFloat32 { 716 panic("overflows float32") 717 } 718 term = float32(f) 719 default: 720 panic("destination value is not an float* or overflows") 721 } 722 723 case ettFloat: 724 if len(packet) < 31 { 725 return nil, nil, errMalformedFloat 726 } 727 728 var f float64 729 if r, err := fmt.Sscanf(string(packet[:31]), "%f", &f); err != nil || r != 1 { 730 return nil, nil, errMalformedFloat 731 } 732 term = f 733 packet = packet[31:] 734 735 if stack == nil { 736 break 737 } 738 739 t := stack.regKeyKind 740 if stack.i&0x01 == 1 { 741 t = stack.regValueKind 742 } 743 switch t { 744 case reflect.Invalid: 745 // not registered type 746 break 747 case reflect.Float64: 748 break 749 case reflect.Float32: 750 if f > math.MaxFloat32 { 751 panic("overflows float32") 752 } 753 term = float32(f) 754 default: 755 panic("destination value is not an float* or overflows") 756 } 757 758 default: 759 term = nil 760 return nil, nil, errMalformedUnknownType 761 } 762 763 // it was a single element 764 if stack == nil && child == nil { 765 break 766 } 767 768 // decoding child item of List/Map/Tuple/Pid/Ref/Port/... going deeper 769 if child != nil { 770 stack = child 771 continue 772 } 773 774 // Stage 2 775 processStack: 776 if stack != nil { 777 var field reflect.Value 778 var set_field bool 779 780 switch stack.termType { 781 case ettList: 782 if stack.i == 0 { 783 // if the first value is atom, check for the registered type 784 if typeName, isAtom := term.(Atom); isAtom == true { 785 registered.RLock() 786 r, found := registered.typesDec[typeName] 787 registered.RUnlock() 788 if found == true { 789 switch r.rtype.Kind() { 790 case reflect.Slice: 791 reg := reflect.MakeSlice(r.rtype, stack.children-2, stack.children-1) 792 stack.reg = ® 793 case reflect.Array: 794 reg := reflect.Indirect(reflect.New(r.rtype)) 795 stack.reg = ® 796 default: 797 if r.strict { 798 panic("destination value of registered type is not a slice/array") 799 } 800 } 801 stack.strict = r.strict 802 if r.strict == false { 803 stack.term.(List)[stack.i] = term 804 } 805 stack.i++ 806 break 807 } 808 } 809 } 810 811 if stack.reg != nil { 812 if stack.i+1 == stack.children { 813 if t != ettNil { 814 x := reflect.Append(*stack.reg, reflect.ValueOf(term)) 815 stack.reg = &x 816 } 817 } else { 818 set_field = true 819 field = stack.reg.Index(stack.i - 1) 820 } 821 822 if stack.strict == true { 823 stack.i++ 824 break 825 } 826 } 827 828 stack.term.(List)[stack.i] = term 829 stack.i++ 830 // remove the last element for proper list (its ettNil) 831 if stack.i == stack.children && t == ettNil { 832 stack.term = stack.term.(List)[:stack.i-1] 833 } 834 835 case ettSmallTuple, ettLargeTuple: 836 837 if stack.i == 0 { 838 // if the first value is atom, check for the registered type 839 if typeName, isAtom := term.(Atom); isAtom == true { 840 registered.RLock() 841 r, found := registered.typesDec[typeName] 842 registered.RUnlock() 843 if found == true { 844 reg := reflect.Indirect(reflect.New(r.rtype)) 845 stack.reg = ® 846 stack.strict = r.strict 847 if r.strict == false { 848 stack.term.(Tuple)[stack.i] = term 849 } 850 stack.i++ 851 break 852 } 853 } 854 } 855 856 if stack.reg != nil { 857 set_field = true 858 field = stack.reg.Field(stack.i - 1) 859 if stack.strict == true { 860 stack.i++ 861 break 862 } 863 } 864 stack.term.(Tuple)[stack.i] = term 865 stack.i++ 866 867 case ettMap: 868 if stack.i == 0 { 869 // if the first key is atom, check for the registered type 870 if typeName, isAtom := term.(Atom); isAtom == true { 871 registered.RLock() 872 r, found := registered.typesDec[typeName] 873 registered.RUnlock() 874 if found == true { 875 if r.rtype.Kind() == reflect.Map { 876 reg := reflect.MakeMapWithSize(r.rtype, stack.children/2) 877 if r.rtype.Key().Kind() != reflect.Interface { 878 stack.regKeyKind = r.rtype.Key().Kind() 879 } 880 if r.rtype.Elem().Kind() != reflect.Interface { 881 stack.regValueKind = r.rtype.Elem().Kind() 882 } 883 stack.reg = ® 884 } else { 885 if r.strict { 886 panic("destination value of registered type is not a map") 887 } 888 } 889 stack.strict = r.strict 890 if r.strict == false { 891 if stack.i&0x01 == 0x01 { // a value 892 stack.term.(Map)[stack.tmp] = term 893 } else { 894 stack.tmp = term 895 } 896 } 897 stack.i++ 898 break 899 } 900 } 901 } 902 if stack.i == 1 && stack.reg != nil && stack.strict == true { 903 // skip it. the value of the key which is the registered type 904 stack.i++ 905 break 906 907 } 908 if stack.i&0x01 == 0x01 { // a value 909 if stack.i > 1 && stack.reg != nil { 910 set_field = true 911 field = *stack.reg 912 } 913 // Erlang can use any value as a key in the map. 914 // OTP 25 sends a message to the 'global_name_server' process 915 // with etf.Tuple as a key in the map, so it caused a panic 916 // and this connection is dropping. 917 switch stack.tmp.(type) { 918 case Tuple: 919 lib.Warning("Erlang sent a etf.Tuple as a map key: %#v => %#v. Ignored this item. Ergo doesn't support it.", stack.tmp, term) 920 default: 921 stack.term.(Map)[stack.tmp] = term 922 } 923 stack.i++ 924 break 925 } 926 927 // a key 928 stack.tmp = term 929 stack.i++ 930 931 case ettPid: 932 if len(packet) < 9 { 933 return nil, nil, errMalformedPid 934 } 935 936 name, ok := term.(Atom) 937 if !ok { 938 return nil, nil, errMalformedPid 939 } 940 pid := Pid{ 941 Node: name, 942 // Same as NEW_PID_EXT except the Creation field is 943 // only one byte and only two bits are significant, 944 // the rest are to be 0. 945 Creation: uint32(packet[8]) & 3, 946 } 947 948 id := uint64(binary.BigEndian.Uint32(packet[:4])) 949 serial := uint64(binary.BigEndian.Uint32(packet[4:8])) 950 if options.FlagBigPidRef { 951 id = id | (serial << 32) 952 } else { 953 // id 15 bits only 2**15 - 1 = 32767 954 // serial 13 bits only 2**13 - 1 = 8191 955 id = (id & 32767) | ((serial & 8191) << 15) 956 } 957 pid.ID = id 958 959 packet = packet[9:] 960 stack.term = pid 961 stack.i++ 962 963 case ettNewPid: 964 if len(packet) < 12 { 965 return nil, nil, errMalformedNewPid 966 } 967 968 name, ok := term.(Atom) 969 if !ok { 970 return nil, nil, errMalformedPid 971 } 972 973 id := uint64(binary.BigEndian.Uint32(packet[:4])) 974 serial := uint64(binary.BigEndian.Uint32(packet[4:8])) 975 pid := Pid{ 976 Node: name, 977 Creation: binary.BigEndian.Uint32(packet[8:12]), 978 } 979 if options.FlagBigPidRef { 980 id = id | (serial << 32) 981 } else { 982 // id 15 bits only 2**15 - 1 = 32767 983 // serial 13 bits only 2**13 - 1 = 8191 984 id = (id & 32767) | ((serial & 8191) << 15) 985 } 986 pid.ID = id 987 988 packet = packet[12:] 989 stack.term = pid 990 stack.i++ 991 992 case ettNewRef: 993 var id uint32 994 name, ok := term.(Atom) 995 if !ok { 996 return nil, nil, errMalformedRef 997 } 998 999 l := stack.tmp.(uint16) 1000 if l > 5 { 1001 return nil, nil, errMalformedRef 1002 } 1003 if l > 3 && !options.FlagBigPidRef { 1004 return nil, nil, errMalformedRef 1005 } 1006 stack.tmp = nil 1007 expectedLength := int(1 + l*4) 1008 1009 if len(packet) < expectedLength { 1010 return nil, nil, errMalformedRef 1011 } 1012 1013 ref := Ref{ 1014 Node: name, 1015 Creation: uint32(packet[0]), 1016 } 1017 packet = packet[1:] 1018 1019 for i := 0; i < int(l); i++ { 1020 // In the first word (4 bytes) of ID, only 18 bits 1021 // are significant, the rest must be 0. 1022 if i == 0 { 1023 // 2**18 - 1 = 262143 1024 id = binary.BigEndian.Uint32(packet[:4]) & 262143 1025 } else { 1026 id = binary.BigEndian.Uint32(packet[:4]) 1027 } 1028 ref.ID[i] = id 1029 packet = packet[4:] 1030 } 1031 1032 stack.term = ref 1033 stack.i++ 1034 1035 case ettNewerRef: 1036 var id uint32 1037 name, ok := term.(Atom) 1038 if !ok { 1039 return nil, nil, errMalformedRef 1040 } 1041 1042 l := stack.tmp.(uint16) 1043 if l > 5 { 1044 return nil, nil, errMalformedRef 1045 } 1046 if l > 3 && !options.FlagBigPidRef { 1047 return nil, nil, errMalformedRef 1048 } 1049 stack.tmp = nil 1050 expectedLength := int(4 + l*4) 1051 1052 if len(packet) < expectedLength { 1053 return nil, nil, errMalformedRef 1054 } 1055 1056 ref := Ref{ 1057 Node: name, 1058 Creation: binary.BigEndian.Uint32(packet[:4]), 1059 } 1060 packet = packet[4:] 1061 1062 for i := 0; i < int(l); i++ { 1063 // In the first word (4 bytes) of ID, only 18 bits 1064 // are significant, the rest must be 0. 1065 if i == 0 { 1066 // 2**18 - 1 = 262143 1067 id = binary.BigEndian.Uint32(packet[:4]) & 262143 1068 } else { 1069 id = binary.BigEndian.Uint32(packet[:4]) 1070 } 1071 ref.ID[i] = id 1072 packet = packet[4:] 1073 } 1074 1075 stack.term = ref 1076 stack.i++ 1077 1078 case ettPort: 1079 if len(packet) < 5 { 1080 return nil, nil, errMalformedPort 1081 } 1082 1083 name, ok := term.(Atom) 1084 if !ok { 1085 return nil, nil, errMalformedPort 1086 } 1087 1088 port := Port{ 1089 Node: name, 1090 ID: binary.BigEndian.Uint32(packet[:4]), 1091 Creation: uint32(packet[4]), 1092 } 1093 1094 packet = packet[5:] 1095 stack.term = port 1096 stack.i++ 1097 1098 case ettNewPort: 1099 if len(packet) < 8 { 1100 return nil, nil, errMalformedNewPort 1101 } 1102 1103 name, ok := term.(Atom) 1104 if !ok { 1105 return nil, nil, errMalformedNewPort 1106 } 1107 1108 port := Port{ 1109 Node: name, 1110 ID: binary.BigEndian.Uint32(packet[:4]), 1111 Creation: binary.BigEndian.Uint32(packet[4:8]), 1112 } 1113 1114 packet = packet[8:] 1115 stack.term = port 1116 stack.i++ 1117 1118 case ettNewFun: 1119 fun := stack.term.(Function) 1120 switch stack.i { 1121 case 0: 1122 // Module 1123 module, ok := term.(Atom) 1124 if !ok { 1125 return nil, nil, errMalformedFun 1126 } 1127 fun.Module = module 1128 1129 case 1: 1130 // OldIndex 1131 oldindex, ok := term.(int) 1132 if !ok { 1133 return nil, nil, errMalformedFun 1134 } 1135 fun.OldIndex = uint32(oldindex) 1136 1137 case 2: 1138 // OldUnique 1139 olduniq, ok := term.(int64) 1140 if !ok { 1141 return nil, nil, errMalformedFun 1142 } 1143 fun.OldUnique = uint32(olduniq) 1144 1145 case 3: 1146 // Pid 1147 pid, ok := term.(Pid) 1148 if !ok { 1149 return nil, nil, errMalformedFun 1150 } 1151 fun.Pid = pid 1152 1153 default: 1154 if len(fun.FreeVars) < (stack.i-4)+1 { 1155 return nil, nil, errMalformedFun 1156 } 1157 fun.FreeVars[stack.i-4] = term 1158 } 1159 1160 stack.term = fun 1161 stack.i++ 1162 1163 case ettExport: 1164 exp := stack.term.(Export) 1165 switch stack.i { 1166 case 0: 1167 module, ok := term.(Atom) 1168 if !ok { 1169 return nil, nil, errMalformedExport 1170 } 1171 exp.Module = module 1172 1173 case 1: 1174 function, ok := term.(Atom) 1175 if !ok { 1176 return nil, nil, errMalformedExport 1177 } 1178 exp.Function = function 1179 1180 case 2: 1181 arity, ok := term.(int) 1182 if !ok { 1183 return nil, nil, errMalformedExport 1184 } 1185 exp.Arity = arity 1186 1187 default: 1188 return nil, nil, errMalformedExport 1189 1190 } 1191 1192 default: 1193 return nil, nil, errInternal 1194 } 1195 1196 if field.Kind() == reflect.Ptr { 1197 pfield := reflect.New(field.Type().Elem()) 1198 field.Set(pfield) 1199 field = pfield.Elem() 1200 } 1201 1202 if set_field && term != nil { 1203 switch field.Kind() { 1204 case reflect.Int8: 1205 switch v := term.(type) { 1206 case int: 1207 if v > math.MaxInt8 || v < math.MinInt8 { 1208 // overflows 1209 if stack.strict { 1210 panic("overflows int8") 1211 } 1212 stack.reg = nil 1213 break 1214 } 1215 field.SetInt(int64(v)) 1216 case int64: 1217 if v > math.MaxInt8 || v < math.MinInt8 { 1218 // overflows 1219 if stack.strict { 1220 panic("overflows int8") 1221 } 1222 stack.reg = nil 1223 break 1224 } 1225 field.SetInt(v) 1226 case uint64: 1227 if v > math.MaxInt8 { 1228 // overflows 1229 if stack.strict { 1230 panic("overflows int8") 1231 } 1232 stack.reg = nil 1233 break 1234 } 1235 field.SetInt(int64(v)) 1236 default: 1237 if stack.strict { 1238 panic("wrong int8 value") 1239 } 1240 stack.reg = nil 1241 } 1242 1243 case reflect.Int16: 1244 switch v := term.(type) { 1245 case int: 1246 if v > math.MaxInt16 || v < math.MinInt16 { 1247 // overflows 1248 if stack.strict { 1249 panic("overflows int16") 1250 } 1251 stack.reg = nil 1252 break 1253 } 1254 field.SetInt(int64(v)) 1255 case int64: 1256 if v > math.MaxInt16 || v < math.MinInt16 { 1257 // overflows 1258 if stack.strict { 1259 panic("overflows int16") 1260 } 1261 stack.reg = nil 1262 break 1263 } 1264 field.SetInt(v) 1265 case uint64: 1266 if v > math.MaxInt16 { 1267 // overflows 1268 if stack.strict { 1269 panic("overflows int16") 1270 } 1271 stack.reg = nil 1272 break 1273 } 1274 field.SetInt(int64(v)) 1275 default: 1276 if stack.strict { 1277 panic("wrong int16 value") 1278 } 1279 stack.reg = nil 1280 } 1281 1282 case reflect.Int32: 1283 switch v := term.(type) { 1284 case int: 1285 if v > math.MaxInt32 || v < math.MinInt32 { 1286 // overflows 1287 if stack.strict { 1288 panic("overflows int32") 1289 } 1290 stack.reg = nil 1291 break 1292 } 1293 field.SetInt(int64(v)) 1294 case int64: 1295 if v > math.MaxInt32 || v < math.MinInt32 { 1296 // overflows 1297 if stack.strict { 1298 panic("overflows int32") 1299 } 1300 stack.reg = nil 1301 break 1302 } 1303 field.SetInt(v) 1304 case uint64: 1305 if v > math.MaxInt32 { 1306 // overflows 1307 if stack.strict { 1308 panic("overflows int32") 1309 } 1310 stack.reg = nil 1311 break 1312 } 1313 field.SetInt(int64(v)) 1314 default: 1315 if stack.strict { 1316 panic("wrong int32 value") 1317 } 1318 stack.reg = nil 1319 } 1320 case reflect.Int64: 1321 switch v := term.(type) { 1322 case int: 1323 field.SetInt(int64(v)) 1324 case int64: 1325 field.SetInt(v) 1326 case uint64: 1327 if v > math.MaxInt64 { 1328 // overflows 1329 if stack.strict { 1330 panic("overflows int64") 1331 } 1332 stack.reg = nil 1333 break 1334 } 1335 field.SetInt(int64(v)) 1336 default: 1337 if stack.strict { 1338 panic("wrong int64 value") 1339 } 1340 stack.reg = nil 1341 } 1342 case reflect.Int: 1343 switch v := term.(type) { 1344 case int: 1345 field.SetInt(int64(v)) 1346 case int64: 1347 if v > math.MaxInt { 1348 // overflows 1349 if stack.strict { 1350 panic("overflows int") 1351 } 1352 stack.reg = nil 1353 break 1354 } 1355 field.SetInt(v) 1356 case uint64: 1357 if v > math.MaxInt { 1358 // overflows 1359 if stack.strict { 1360 panic("overflows int") 1361 } 1362 stack.reg = nil 1363 break 1364 } 1365 field.SetInt(int64(v)) 1366 default: 1367 if stack.strict { 1368 panic("wrong int value") 1369 } 1370 stack.reg = nil 1371 } 1372 1373 case reflect.Uint8: 1374 switch v := term.(type) { 1375 case int: 1376 if int64(v) > math.MaxUint8 || v < 0 { 1377 // overflows 1378 if stack.strict { 1379 panic("overflows uint8") 1380 } 1381 stack.reg = nil 1382 break 1383 } 1384 field.SetUint(uint64(v)) 1385 case int64: 1386 if v > math.MaxUint8 || v < 0 { 1387 // overflows 1388 if stack.strict { 1389 panic("overflows uint8") 1390 } 1391 stack.reg = nil 1392 break 1393 } 1394 field.SetUint(uint64(v)) 1395 case uint64: 1396 if v > math.MaxUint8 { 1397 // overflows 1398 if stack.strict { 1399 panic("overflows uint8") 1400 } 1401 stack.reg = nil 1402 break 1403 } 1404 field.SetUint(v) 1405 default: 1406 if stack.strict { 1407 panic("wrong uint8 value") 1408 } 1409 stack.reg = nil 1410 } 1411 1412 case reflect.Uint16: 1413 switch v := term.(type) { 1414 case int: 1415 if int64(v) > math.MaxUint16 || v < 0 { 1416 // overflows 1417 if stack.strict { 1418 panic("overflows uint16") 1419 } 1420 stack.reg = nil 1421 break 1422 } 1423 field.SetUint(uint64(v)) 1424 case int64: 1425 if v > math.MaxUint16 || v < 0 { 1426 // overflows 1427 if stack.strict { 1428 panic("overflows uint16") 1429 } 1430 stack.reg = nil 1431 break 1432 } 1433 field.SetUint(uint64(v)) 1434 case uint64: 1435 if v > math.MaxUint16 { 1436 // overflows 1437 if stack.strict { 1438 panic("overflows uint16") 1439 } 1440 stack.reg = nil 1441 break 1442 } 1443 field.SetUint(v) 1444 default: 1445 if stack.strict { 1446 panic("wrong uint16 value") 1447 } 1448 stack.reg = nil 1449 } 1450 case reflect.Uint32: 1451 switch v := term.(type) { 1452 case int: 1453 if int64(v) > math.MaxUint32 || v < 0 { 1454 // overflows 1455 if stack.strict { 1456 panic("overflows uint32") 1457 } 1458 stack.reg = nil 1459 break 1460 } 1461 field.SetUint(uint64(v)) 1462 case int64: 1463 if v > math.MaxUint32 || v < 0 { 1464 // overflows 1465 if stack.strict { 1466 panic("overflows uint32") 1467 } 1468 stack.reg = nil 1469 break 1470 } 1471 field.SetUint(uint64(v)) 1472 case uint64: 1473 if v > math.MaxUint32 { 1474 // overflows 1475 if stack.strict { 1476 panic("overflows uint32") 1477 } 1478 stack.reg = nil 1479 break 1480 } 1481 field.SetUint(v) 1482 default: 1483 if stack.strict { 1484 panic("wrong uint32 value") 1485 } 1486 stack.reg = nil 1487 } 1488 1489 case reflect.Uint64: 1490 switch v := term.(type) { 1491 case int: 1492 if v < 0 { 1493 // overflows 1494 if stack.strict { 1495 panic("overflows uint64") 1496 } 1497 stack.reg = nil 1498 break 1499 } 1500 field.SetUint(uint64(v)) 1501 case int64: 1502 if v < 0 { 1503 // overflows 1504 if stack.strict { 1505 panic("overflows uint64") 1506 } 1507 stack.reg = nil 1508 break 1509 } 1510 field.SetUint(uint64(v)) 1511 case uint64: 1512 field.SetUint(v) 1513 default: 1514 if stack.strict { 1515 panic("wrong uint64 value") 1516 } 1517 stack.reg = nil 1518 } 1519 1520 case reflect.Uint: 1521 switch v := term.(type) { 1522 case int: 1523 if v < 0 { 1524 // overflows 1525 if stack.strict { 1526 panic("overflows uint") 1527 } 1528 stack.reg = nil 1529 break 1530 } 1531 field.SetUint(uint64(v)) 1532 case int64: 1533 if v > math.MaxInt || v < 0 { 1534 // overflows 1535 if stack.strict { 1536 panic("overflows uint") 1537 } 1538 stack.reg = nil 1539 break 1540 } 1541 field.SetUint(uint64(v)) 1542 case uint64: 1543 if v > math.MaxUint { 1544 // overflows 1545 if stack.strict { 1546 panic("overflows uint") 1547 } 1548 stack.reg = nil 1549 break 1550 } 1551 field.SetUint(v) 1552 default: 1553 if stack.strict { 1554 panic("wrong uint value") 1555 } 1556 stack.reg = nil 1557 } 1558 case reflect.Float32: 1559 f, ok := term.(float64) 1560 if ok == false { 1561 if stack.strict { 1562 panic("wrong float value") 1563 } 1564 stack.reg = nil 1565 break 1566 } 1567 field.SetFloat(f) 1568 1569 case reflect.Float64: 1570 f64, ok := term.(float64) 1571 if ok == false { 1572 if stack.strict { 1573 panic("wrong float64") 1574 } 1575 stack.reg = nil 1576 break 1577 } 1578 field.SetFloat(f64) 1579 1580 case reflect.String: 1581 switch v := term.(type) { 1582 case List: 1583 s, err := convertCharlistToString(v) 1584 if err != nil { 1585 if stack.strict { 1586 panic("can't convert charlist into string") 1587 } 1588 stack.reg = nil 1589 break 1590 } 1591 field.SetString(s) 1592 case []byte: 1593 field.SetString(string(v)) 1594 case string: 1595 field.SetString(v) 1596 case Atom: 1597 field.SetString(string(v)) 1598 default: 1599 if stack.strict { 1600 panic("wrong string value") 1601 } 1602 stack.reg = nil 1603 } 1604 case reflect.Bool: 1605 b, ok := term.(bool) 1606 if !ok { 1607 if stack.strict { 1608 panic("wrong bool value") 1609 } 1610 stack.reg = nil 1611 break 1612 } 1613 field.SetBool(b) 1614 1615 case reflect.Map: 1616 if stack.tmp == nil { 1617 field.Set(reflect.ValueOf(term)) 1618 break 1619 } 1620 destkey := reflect.ValueOf(stack.tmp) 1621 destval := reflect.ValueOf(term) 1622 stack.reg.SetMapIndex(destkey, destval) 1623 1624 default: 1625 if stack.strict { 1626 if field.Type().Name() == "Alias" { 1627 term = Alias(term.(Ref)) 1628 } 1629 field.Set(reflect.ValueOf(term)) 1630 } else { 1631 // wrap it to catch the panic 1632 setValue := func(f reflect.Value, v interface{}) (ok bool) { 1633 if lib.CatchPanic() { 1634 defer func() { 1635 if r := recover(); r != nil { 1636 ok = false 1637 } 1638 }() 1639 } 1640 if field.Type().Name() == "Alias" { 1641 v = Alias(v.(Ref)) 1642 } 1643 f.Set(reflect.ValueOf(v)) 1644 return true 1645 } 1646 if setValue(field, term) == false { 1647 stack.reg = nil 1648 } 1649 1650 } 1651 } 1652 1653 } 1654 1655 } 1656 1657 // we are still decoding children of Lis/Map/Tuple/... 1658 if stack.i < stack.children { 1659 continue 1660 } 1661 1662 if stack.reg != nil { 1663 term = (*stack.reg).Interface() 1664 } else { 1665 term = stack.term 1666 } 1667 1668 // this term was the last element of List/Map/Tuple/... 1669 // pop from the stack, but if its the root just finish 1670 if stack.parent == nil { 1671 break 1672 } 1673 1674 stack, stack.parent = stack.parent, nil // nil here is just a little help for GC 1675 goto processStack 1676 1677 } 1678 1679 return term, packet, nil 1680 }