forked from mirrors/gecko-dev
		
	 025f5fb9f0
			
		
	
	
		025f5fb9f0
		
	
	
	
	
		
			
			This backs out all work from bug 1627075 as well as all of its descendents. There were a few conflicts when backing this out but overall it was pretty clean, so I would say it's a fairly mild level of risk. Historically Nathan Froyd has reviewed these patches, but he is no longer at Mozilla, and no one else is particularly familiar with the code, so I am passing this off to RyanVM who has at least been familiar with the history of the bug. Differential Revision: https://phabricator.services.mozilla.com/D90096
		
			
				
	
	
		
			148 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef IOBuffers_h
 | |
| #define IOBuffers_h
 | |
| 
 | |
| #include "mozilla/Assertions.h"
 | |
| #include "mozilla/CheckedInt.h"
 | |
| #include "mozilla/EndianUtils.h"
 | |
| #include "mozilla/EnumSet.h"
 | |
| #include "mozilla/Range.h"
 | |
| #include "mozilla/Span.h"
 | |
| #include "nsString.h"
 | |
| #include "nsTArray.h"
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace loader {
 | |
| 
 | |
| class OutputBuffer {
 | |
|  public:
 | |
|   OutputBuffer() {}
 | |
| 
 | |
|   uint8_t* write(size_t size) {
 | |
|     auto buf = data.AppendElements(size);
 | |
|     cursor_ += size;
 | |
|     return buf;
 | |
|   }
 | |
| 
 | |
|   void codeUint8(const uint8_t& val) { *write(sizeof val) = val; }
 | |
| 
 | |
|   template <typename T>
 | |
|   void codeUint8(const EnumSet<T>& val) {
 | |
|     // EnumSets are always represented as uint32_t values, so we need to
 | |
|     // assert that the value actually fits in a uint8 before writing it.
 | |
|     uint32_t value = val.serialize();
 | |
|     codeUint8(CheckedUint8(value).value());
 | |
|   }
 | |
| 
 | |
|   void codeUint16(const uint16_t& val) {
 | |
|     LittleEndian::writeUint16(write(sizeof val), val);
 | |
|   }
 | |
| 
 | |
|   void codeUint32(const uint32_t& val) {
 | |
|     LittleEndian::writeUint32(write(sizeof val), val);
 | |
|   }
 | |
| 
 | |
|   void codeString(const nsCString& str) {
 | |
|     auto len = CheckedUint16(str.Length()).value();
 | |
| 
 | |
|     codeUint16(len);
 | |
|     memcpy(write(len), str.BeginReading(), len);
 | |
|   }
 | |
| 
 | |
|   size_t cursor() const { return cursor_; }
 | |
| 
 | |
|   uint8_t* Get() { return data.Elements(); }
 | |
| 
 | |
|   const uint8_t* Get() const { return data.Elements(); }
 | |
| 
 | |
|  private:
 | |
|   nsTArray<uint8_t> data;
 | |
|   size_t cursor_ = 0;
 | |
| };
 | |
| 
 | |
| class InputBuffer {
 | |
|  public:
 | |
|   explicit InputBuffer(const Range<uint8_t>& buffer) : data(buffer) {}
 | |
| 
 | |
|   const uint8_t* read(size_t size) {
 | |
|     MOZ_ASSERT(checkCapacity(size));
 | |
| 
 | |
|     auto buf = &data[cursor_];
 | |
|     cursor_ += size;
 | |
|     return buf;
 | |
|   }
 | |
| 
 | |
|   bool codeUint8(uint8_t& val) {
 | |
|     if (checkCapacity(sizeof val)) {
 | |
|       val = *read(sizeof val);
 | |
|     }
 | |
|     return !error_;
 | |
|   }
 | |
| 
 | |
|   template <typename T>
 | |
|   bool codeUint8(EnumSet<T>& val) {
 | |
|     uint8_t value;
 | |
|     if (codeUint8(value)) {
 | |
|       val.deserialize(value);
 | |
|     }
 | |
|     return !error_;
 | |
|   }
 | |
| 
 | |
|   bool codeUint16(uint16_t& val) {
 | |
|     if (checkCapacity(sizeof val)) {
 | |
|       val = LittleEndian::readUint16(read(sizeof val));
 | |
|     }
 | |
|     return !error_;
 | |
|   }
 | |
| 
 | |
|   bool codeUint32(uint32_t& val) {
 | |
|     if (checkCapacity(sizeof val)) {
 | |
|       val = LittleEndian::readUint32(read(sizeof val));
 | |
|     }
 | |
|     return !error_;
 | |
|   }
 | |
| 
 | |
|   bool codeString(nsCString& str) {
 | |
|     uint16_t len;
 | |
|     if (codeUint16(len)) {
 | |
|       if (checkCapacity(len)) {
 | |
|         str.SetLength(len);
 | |
|         memcpy(str.BeginWriting(), read(len), len);
 | |
|       }
 | |
|     }
 | |
|     return !error_;
 | |
|   }
 | |
| 
 | |
|   bool error() { return error_; }
 | |
| 
 | |
|   bool finished() { return error_ || !remainingCapacity(); }
 | |
| 
 | |
|   size_t remainingCapacity() { return data.length() - cursor_; }
 | |
| 
 | |
|   size_t cursor() const { return cursor_; }
 | |
| 
 | |
|   const uint8_t* Get() const { return data.begin().get(); }
 | |
| 
 | |
|  private:
 | |
|   bool checkCapacity(size_t size) {
 | |
|     if (size > remainingCapacity()) {
 | |
|       error_ = true;
 | |
|     }
 | |
|     return !error_;
 | |
|   }
 | |
| 
 | |
|   bool error_ = false;
 | |
| 
 | |
|  public:
 | |
|   const Range<uint8_t>& data;
 | |
|   size_t cursor_ = 0;
 | |
| };
 | |
| 
 | |
| }  // namespace loader
 | |
| }  // namespace mozilla
 | |
| 
 | |
| #endif  // IOBuffers_h
 |