verifier.go 3.9 KB

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