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