1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef LIBZIPARCHIVE_ENTRY_NAME_UTILS_INL_H_
18 #define LIBZIPARCHIVE_ENTRY_NAME_UTILS_INL_H_
19 
20 #include <stddef.h>
21 #include <stdint.h>
22 
23 #include <limits>
24 
25 // Check if |length| bytes at |entry_name| constitute a valid entry name.
26 // Entry names must be valid UTF-8 and must not contain '0'. They also must
27 // fit into the central directory record.
IsValidEntryName(const uint8_t * entry_name,const size_t length)28 inline bool IsValidEntryName(const uint8_t* entry_name, const size_t length) {
29   if (length > std::numeric_limits<uint16_t>::max()) {
30     return false;
31   }
32   for (size_t i = 0; i < length; ++i) {
33     const uint8_t byte = entry_name[i];
34     if (byte == 0) {
35       return false;
36     } else if ((byte & 0x80) == 0) {
37       // Single byte sequence.
38       continue;
39     } else if ((byte & 0xc0) == 0x80 || (byte & 0xfe) == 0xfe) {
40       // Invalid sequence.
41       return false;
42     } else {
43       // 2-5 byte sequences.
44       for (uint8_t first = static_cast<uint8_t>((byte & 0x7f) << 1); first & 0x80;
45            first = static_cast<uint8_t>((first & 0x7f) << 1)) {
46         ++i;
47 
48         // Missing continuation byte..
49         if (i == length) {
50           return false;
51         }
52 
53         // Invalid continuation byte.
54         const uint8_t continuation_byte = entry_name[i];
55         if ((continuation_byte & 0xc0) != 0x80) {
56           return false;
57         }
58       }
59     }
60   }
61 
62   return true;
63 }
64 
65 #endif  // LIBZIPARCHIVE_ENTRY_NAME_UTILS_INL_H_
66