verifier.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package maxminddb
  2. import "reflect"
  3. type verifier struct {
  4. reader *Reader
  5. }
  6. // Verify checks that the database is valid. It validates the search tree,
  7. // the data section, and the metadata section. This verifier is stricter than
  8. // the specification and may return errors on databases that are readable.
  9. func (r *Reader) Verify() error {
  10. v := verifier{r}
  11. if err := v.verifyMetadata(); err != nil {
  12. return err
  13. }
  14. return v.verifyDatabase()
  15. }
  16. func (v *verifier) verifyMetadata() error {
  17. metadata := v.reader.Metadata
  18. if metadata.BinaryFormatMajorVersion != 2 {
  19. return testError(
  20. "binary_format_major_version",
  21. 2,
  22. metadata.BinaryFormatMajorVersion,
  23. )
  24. }
  25. if metadata.BinaryFormatMinorVersion != 0 {
  26. return testError(
  27. "binary_format_minor_version",
  28. 0,
  29. metadata.BinaryFormatMinorVersion,
  30. )
  31. }
  32. if metadata.DatabaseType == "" {
  33. return testError(
  34. "database_type",
  35. "non-empty string",
  36. metadata.DatabaseType,
  37. )
  38. }
  39. if len(metadata.Description) == 0 {
  40. return testError(
  41. "description",
  42. "non-empty slice",
  43. metadata.Description,
  44. )
  45. }
  46. if metadata.IPVersion != 4 && metadata.IPVersion != 6 {
  47. return testError(
  48. "ip_version",
  49. "4 or 6",
  50. metadata.IPVersion,
  51. )
  52. }
  53. if metadata.RecordSize != 24 &&
  54. metadata.RecordSize != 28 &&
  55. metadata.RecordSize != 32 {
  56. return testError(
  57. "record_size",
  58. "24, 28, or 32",
  59. metadata.RecordSize,
  60. )
  61. }
  62. if metadata.NodeCount == 0 {
  63. return testError(
  64. "node_count",
  65. "positive integer",
  66. metadata.NodeCount,
  67. )
  68. }
  69. return nil
  70. }
  71. func (v *verifier) verifyDatabase() error {
  72. offsets, err := v.verifySearchTree()
  73. if err != nil {
  74. return err
  75. }
  76. if err := v.verifyDataSectionSeparator(); err != nil {
  77. return err
  78. }
  79. return v.verifyDataSection(offsets)
  80. }
  81. func (v *verifier) verifySearchTree() (map[uint]bool, error) {
  82. offsets := make(map[uint]bool)
  83. it := v.reader.Networks()
  84. for it.Next() {
  85. offset, err := v.reader.resolveDataPointer(it.lastNode.pointer)
  86. if err != nil {
  87. return nil, err
  88. }
  89. offsets[uint(offset)] = true
  90. }
  91. if err := it.Err(); err != nil {
  92. return nil, err
  93. }
  94. return offsets, nil
  95. }
  96. func (v *verifier) verifyDataSectionSeparator() error {
  97. separatorStart := v.reader.Metadata.NodeCount * v.reader.Metadata.RecordSize / 4
  98. separator := v.reader.buffer[separatorStart : separatorStart+dataSectionSeparatorSize]
  99. for _, b := range separator {
  100. if b != 0 {
  101. return newInvalidDatabaseError("unexpected byte in data separator: %v", separator)
  102. }
  103. }
  104. return nil
  105. }
  106. func (v *verifier) verifyDataSection(offsets map[uint]bool) error {
  107. pointerCount := len(offsets)
  108. decoder := v.reader.decoder
  109. var offset uint
  110. bufferLen := uint(len(decoder.buffer))
  111. for offset < bufferLen {
  112. var data interface{}
  113. rv := reflect.ValueOf(&data)
  114. newOffset, err := decoder.decode(offset, rv, 0)
  115. if err != nil {
  116. return newInvalidDatabaseError("received decoding error (%v) at offset of %v", err, offset)
  117. }
  118. if newOffset <= offset {
  119. return newInvalidDatabaseError("data section offset unexpectedly went from %v to %v", offset, newOffset)
  120. }
  121. pointer := offset
  122. if _, ok := offsets[pointer]; ok {
  123. delete(offsets, pointer)
  124. } else {
  125. return newInvalidDatabaseError("found data (%v) at %v that the search tree does not point to", data, pointer)
  126. }
  127. offset = newOffset
  128. }
  129. if offset != bufferLen {
  130. return newInvalidDatabaseError(
  131. "unexpected data at the end of the data section (last offset: %v, end: %v)",
  132. offset,
  133. bufferLen,
  134. )
  135. }
  136. if len(offsets) != 0 {
  137. return newInvalidDatabaseError(
  138. "found %v pointers (of %v) in the search tree that we did not see in the data section",
  139. len(offsets),
  140. pointerCount,
  141. )
  142. }
  143. return nil
  144. }
  145. func testError(
  146. field string,
  147. expected interface{},
  148. actual interface{},
  149. ) error {
  150. return newInvalidDatabaseError(
  151. "%v - Expected: %v Actual: %v",
  152. field,
  153. expected,
  154. actual,
  155. )
  156. }