1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <string.h>
6 
7 #include "base/numerics/safe_math.h"
8 #include "third_party/hunspell/google/bdict.h"
9 
10 // static
Verify(const char * bdict_data,size_t bdict_length)11 bool hunspell::BDict::Verify(const char* bdict_data, size_t bdict_length) {
12   if (bdict_length <= sizeof(hunspell::BDict::Header))
13     return false;
14 
15   const BDict::Header* header =
16       reinterpret_cast<const hunspell::BDict::Header*>(bdict_data);
17   if (header->signature != hunspell::BDict::SIGNATURE ||
18       header->major_version > hunspell::BDict::MAJOR_VERSION ||
19       header->aff_offset > bdict_length ||
20       header->dic_offset > bdict_length) {
21     return false;
22   }
23 
24   {
25     // Make sure there is enough room for the affix header.
26     base::CheckedNumeric<uint32_t> aff_offset(header->aff_offset);
27     aff_offset += sizeof(hunspell::BDict::AffHeader);
28     if (!aff_offset.IsValid() || aff_offset.ValueOrDie() > bdict_length)
29       return false;
30   }
31 
32   const hunspell::BDict::AffHeader* aff_header =
33       reinterpret_cast<const hunspell::BDict::AffHeader*>(
34           &bdict_data[header->aff_offset]);
35 
36   // Make sure there is enough room for the affix group count dword.
37   {
38     base::CheckedNumeric<uint32_t> affix_group_offset(
39         aff_header->affix_group_offset);
40     affix_group_offset += sizeof(uint32_t);
41     if (!affix_group_offset.IsValid() ||
42         affix_group_offset.ValueOrDie() > bdict_length) {
43       return false;
44     }
45   }
46 
47   // The new BDICT header has a MD5 digest of the dictionary data. Compare the
48   // MD5 digest of the data with the one in the BDICT header.
49   if (header->major_version >= 2) {
50     base::MD5Digest digest;
51     base::MD5Sum(aff_header, bdict_length - header->aff_offset, &digest);
52     if (memcmp(&digest, &header->digest, sizeof(digest)))
53       return false;
54   }
55 
56   return true;
57 }
58