File indexing completed on 2024-05-12 17:15:22
0001 /* 0002 Copyright (C) 2016 Andreas Hartmetz <ahartmetz@gmail.com> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LGPL. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 0019 Alternatively, this file is available under the Mozilla Public License 0020 Version 1.1. You may obtain a copy of the License at 0021 http://www.mozilla.org/MPL/ 0022 */ 0023 0024 #include "arguments.h" 0025 0026 #include "../testutil.h" 0027 0028 #include <cstring> 0029 #include <iostream> 0030 0031 static void test_arrayLength() 0032 { 0033 const uint32 maxInt32Count = Arguments::MaxArrayLength / sizeof(uint32); 0034 for (int i = 0; i < 2; i++) { 0035 const bool withVariant = i == 1; 0036 { 0037 Arguments::Writer writer; 0038 if (withVariant) { 0039 writer.beginVariant(); 0040 } 0041 writer.beginArray(); 0042 for (uint32 j = 0; j < maxInt32Count; j++) { 0043 writer.writeUint32(j); 0044 } 0045 writer.endArray(); 0046 if (withVariant) { 0047 TEST(writer.state() != Arguments::InvalidData); 0048 writer.endVariant(); 0049 } 0050 Arguments arg = writer.finish(); 0051 TEST(writer.state() == Arguments::Finished); 0052 } 0053 { 0054 Arguments::Writer writer; 0055 if (withVariant) { 0056 writer.beginVariant(); 0057 } 0058 writer.beginArray(); 0059 for (uint32 j = 0; j < maxInt32Count + 1; j++) { 0060 writer.writeUint32(j); 0061 } 0062 writer.endArray(); 0063 if (withVariant) { 0064 TEST(writer.state() != Arguments::InvalidData); 0065 writer.endVariant(); 0066 } 0067 TEST(writer.state() == Arguments::InvalidData); 0068 } 0069 } 0070 0071 // Note: No need to test dicts, they are implemented pretty much like arrays regarding limits 0072 0073 // The following two tests are overspecific to the implementation - it can only "guess" the full final 0074 // message size because it simply isn't known in the ArgumentList. Still better than nothing. 0075 { 0076 Arguments::Writer writer; 0077 for (uint32 i = 0; i < 2; i++) { 0078 writer.beginArray(); 0079 // -2 because array length prefix adds one uint32 per array, and we must also subtract 0080 // (signature + alignment padding to 8 byte boundary), i.e. 8 bytes, / 2 = one more 0081 // sizeof(uint32) per array. 0082 for (uint32 j = 0; j < maxInt32Count - 2; j++) { 0083 writer.writeUint32(j); 0084 } 0085 writer.endArray(); 0086 } 0087 TEST(writer.state() != Arguments::InvalidData); 0088 Arguments arg = writer.finish(); 0089 TEST(writer.state() == Arguments::Finished); 0090 } 0091 { 0092 Arguments::Writer writer; 0093 for (uint32 i = 0; i < 2; i++) { 0094 writer.beginArray(); 0095 for (uint32 j = 0; j < maxInt32Count - 1; j++) { 0096 writer.writeUint32(j); 0097 } 0098 writer.endArray(); 0099 } 0100 writer.writeByte(123); // one byte too many! 0101 TEST(writer.state() != Arguments::InvalidData); 0102 Arguments arg = writer.finish(); 0103 TEST(writer.state() == Arguments::InvalidData); 0104 } 0105 } 0106 0107 static void test_argumentsLength() 0108 { 0109 static const uint32 bufferSize = Arguments::MaxArrayLength + 1024; 0110 byte *buffer = static_cast<byte *>(malloc(bufferSize)); 0111 memset(buffer, 0, bufferSize); 0112 0113 // Gross max length violations should be caught early 0114 for (int i = 0; i < 2; i++) { 0115 const bool withVariant = i == 1; 0116 0117 Arguments::Writer writer; 0118 for (int j = 0; j < 4; j++) { 0119 if (withVariant) { 0120 writer.beginVariant(); 0121 writer.beginStruct(); 0122 } 0123 writer.writePrimitiveArray(Arguments::Byte, chunk(buffer, Arguments::MaxArrayLength)); 0124 if (j == 1) { 0125 // Now just over max size. Require the length check in Writer to be lenient before 0126 // finish() - that is expected of the current implementation. 0127 if (withVariant) { 0128 for (int k = 0; k <= j; k++) { 0129 writer.endStruct(); 0130 writer.endVariant(); 0131 } 0132 } 0133 Arguments::Writer writer2(writer); 0134 TEST(writer2.state() != Arguments::InvalidData); 0135 writer2.finish(); 0136 TEST(writer2.state() == Arguments::InvalidData); 0137 } 0138 } 0139 TEST(writer.state() == Arguments::InvalidData); 0140 } 0141 0142 // Test message size exactly at maximum and exactly 1 byte over 0143 for (int i = 0; i < 4; i++) { 0144 const bool makeTooLong = i & 1; 0145 const bool withVariant = i & 2; 0146 0147 Arguments::Writer writer; 0148 // note: Arguments does not count Arguments::signature() length towards length 0149 uint32 left = Arguments::MaxMessageLength; 0150 writer.writePrimitiveArray(Arguments::Byte, chunk(buffer, Arguments::MaxArrayLength)); 0151 left -= 2 * sizeof(uint32) + Arguments::MaxArrayLength; // sizeof(uint32): array length field 0152 if (withVariant) { 0153 left -= 3; // variant signature "s", no alignment before next element 0154 } 0155 writer.writePrimitiveArray(Arguments::Byte, chunk(buffer, left - 4)); 0156 // Now there are exactly 4 bytes left to MaxMessageLength 0157 0158 TEST(writer.state() != Arguments::InvalidData); 0159 0160 if (withVariant) { 0161 writer.beginVariant(); 0162 } 0163 // Write a signature because it requires no alignment and its size can be anything from 2 to 257 0164 if (makeTooLong) { 0165 writer.writeSignature(cstring("xxx")); // + one byte length prefix + null terminator = 5 bytes 0166 } else { 0167 writer.writeSignature(cstring("xx")); 0168 } 0169 if (withVariant) { 0170 writer.endVariant(); 0171 } 0172 TEST(writer.state() != Arguments::InvalidData); 0173 writer.finish(); 0174 if (makeTooLong) { 0175 TEST(writer.state() == Arguments::InvalidData); 0176 } else { 0177 TEST(writer.state() == Arguments::Finished); 0178 } 0179 } 0180 } 0181 0182 int main(int, char *[]) 0183 { 0184 test_arrayLength(); 0185 test_argumentsLength(); 0186 std::cout << "Passed!\n"; 0187 }