diff options
author | Caleb Raitto <caraitto@chromium.org> | 2020-07-23 01:45:27 +0000 |
---|---|---|
committer | Michael BrĂ¼ning <michael.bruning@qt.io> | 2020-10-27 09:29:27 +0000 |
commit | 9d173d02d5ec0a2a3e3051ced579d0507d5bcf54 (patch) | |
tree | c1afc12050884af3d14cfc3b674287be5bf3c39b | |
parent | 6ef8f4ed82915703d25c80ace6148e5e1413a78e (diff) | |
download | qtwebengine-chromium-9d173d02d5ec0a2a3e3051ced579d0507d5bcf54.tar.gz |
[Backport] Security bug 1106091
Manual backport of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/2309004:
Remove SimpleSerialize() and SimpleDeserialize().
By handling serialization of each type explicitly, we avoid serializing
padding bytes.
Bug: 973801,1106091
Change-Id: I9f4e6b82fb484b9256b25b531cc2d51c800425bb
Commit-Queue: Khushal <khushalsagar@chromium.org>
Reviewed-by: Khushal <khushalsagar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791110}
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r-- | chromium/cc/paint/paint_op_buffer.cc | 317 | ||||
-rw-r--r-- | chromium/cc/paint/paint_op_buffer.h | 31 | ||||
-rw-r--r-- | chromium/cc/paint/paint_op_reader.h | 9 | ||||
-rw-r--r-- | chromium/cc/paint/paint_op_writer.h | 3 |
4 files changed, 280 insertions, 80 deletions
diff --git a/chromium/cc/paint/paint_op_buffer.cc b/chromium/cc/paint/paint_op_buffer.cc index 6417c049cde..5f21d6c82b6 100644 --- a/chromium/cc/paint/paint_op_buffer.cc +++ b/chromium/cc/paint/paint_op_buffer.cc @@ -306,14 +306,6 @@ std::ostream& operator<<(std::ostream& os, PaintOpType type) { return os << PaintOpTypeToString(type); } -template <typename T> -size_t SimpleSerialize(const PaintOp* op, void* memory, size_t size) { - if (sizeof(T) > size) - return 0; - memcpy(memory, op, sizeof(T)); - return sizeof(T); -} - PlaybackParams::PlaybackParams(ImageProvider* image_provider) : image_provider(image_provider), original_ctm(SkMatrix::I()), @@ -401,39 +393,59 @@ size_t ClipPathOp::Serialize(const PaintOp* base_op, return helper.size(); } -size_t ClipRectOp::Serialize(const PaintOp* op, +size_t ClipRectOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<ClipRectOp>(op, memory, size); + auto* op = static_cast<const ClipRectOp*>(base_op); + PaintOpWriter helper(memory, size, options); + helper.Write(op->rect); + helper.Write(op->op); + helper.Write(op->antialias); + return helper.size(); } -size_t ClipRRectOp::Serialize(const PaintOp* op, +size_t ClipRRectOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<ClipRRectOp>(op, memory, size); + auto* op = static_cast<const ClipRRectOp*>(base_op); + PaintOpWriter helper(memory, size, options); + helper.Write(op->rrect); + helper.Write(op->op); + helper.Write(op->antialias); + return helper.size(); } -size_t ConcatOp::Serialize(const PaintOp* op, +size_t ConcatOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<ConcatOp>(op, memory, size); + auto* op = static_cast<const ConcatOp*>(base_op); + PaintOpWriter helper(memory, size, options); + helper.Write(op->matrix); + return helper.size(); } -size_t CustomDataOp::Serialize(const PaintOp* op, +size_t CustomDataOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<CustomDataOp>(op, memory, size); + auto* op = static_cast<const CustomDataOp*>(base_op); + PaintOpWriter helper(memory, size, options); + helper.Write(op->id); + return helper.size(); } -size_t DrawColorOp::Serialize(const PaintOp* op, +size_t DrawColorOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<DrawColorOp>(op, memory, size); + auto* op = static_cast<const DrawColorOp*>(base_op); + PaintOpWriter helper(memory, size, options); + helper.Write(op->color); + helper.Write(op->mode); + return helper.size(); } size_t DrawDRRectOp::Serialize(const PaintOp* base_op, @@ -639,32 +651,38 @@ size_t DrawTextBlobOp::Serialize(const PaintOp* base_op, return helper.size(); } -size_t NoopOp::Serialize(const PaintOp* op, +size_t NoopOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<NoopOp>(op, memory, size); + PaintOpWriter helper(memory, size, options); + return helper.size(); } -size_t RestoreOp::Serialize(const PaintOp* op, +size_t RestoreOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<RestoreOp>(op, memory, size); + PaintOpWriter helper(memory, size, options); + return helper.size(); } -size_t RotateOp::Serialize(const PaintOp* op, +size_t RotateOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<RotateOp>(op, memory, size); + auto* op = static_cast<const RotateOp*>(base_op); + PaintOpWriter helper(memory, size, options); + helper.Write(op->degrees); + return helper.size(); } -size_t SaveOp::Serialize(const PaintOp* op, +size_t SaveOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<SaveOp>(op, memory, size); + PaintOpWriter helper(memory, size, options); + return helper.size(); } size_t SaveLayerOp::Serialize(const PaintOp* base_op, @@ -681,44 +699,64 @@ size_t SaveLayerOp::Serialize(const PaintOp* base_op, return helper.size(); } -size_t SaveLayerAlphaOp::Serialize(const PaintOp* op, +size_t SaveLayerAlphaOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<SaveLayerAlphaOp>(op, memory, size); + auto* op = static_cast<const SaveLayerAlphaOp*>(base_op); + PaintOpWriter helper(memory, size, options); + helper.Write(op->bounds); + helper.Write(op->alpha); + return helper.size(); } -size_t ScaleOp::Serialize(const PaintOp* op, +size_t ScaleOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<ScaleOp>(op, memory, size); + auto* op = static_cast<const ScaleOp*>(base_op); + PaintOpWriter helper(memory, size, options); + helper.Write(op->sx); + helper.Write(op->sy); + return helper.size(); } -size_t SetMatrixOp::Serialize(const PaintOp* op, +size_t SetMatrixOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - if (options.original_ctm.isIdentity()) - return SimpleSerialize<SetMatrixOp>(op, memory, size); + auto* op = static_cast<const SetMatrixOp*>(base_op); + PaintOpWriter helper(memory, size, options); - SetMatrixOp transformed(*static_cast<const SetMatrixOp*>(op)); - transformed.matrix.postConcat(options.original_ctm); - return SimpleSerialize<SetMatrixOp>(&transformed, memory, size); + if (options.original_ctm.isIdentity()) { + helper.Write(op->matrix); + } else { + SkMatrix transformed = op->matrix; + transformed.postConcat(options.original_ctm); + helper.Write(transformed); + } + return helper.size(); } -size_t SetNodeIdOp::Serialize(const PaintOp* op, +size_t SetNodeIdOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<SetNodeIdOp>(op, memory, size); + auto* op = static_cast<const SetNodeIdOp*>(base_op); + PaintOpWriter helper(memory, size, options); + helper.Write(op->node_id); + return helper.size(); } -size_t TranslateOp::Serialize(const PaintOp* op, +size_t TranslateOp::Serialize(const PaintOp* base_op, void* memory, size_t size, const SerializeOptions& options) { - return SimpleSerialize<TranslateOp>(op, memory, size); + auto* op = static_cast<const TranslateOp*>(base_op); + PaintOpWriter helper(memory, size, options); + helper.Write(op->dx); + helper.Write(op->dy); + return helper.size(); } template <typename T> @@ -727,24 +765,6 @@ void UpdateTypeAndSkip(T* op) { op->skip = PaintOpBuffer::ComputeOpSkip(sizeof(T)); } -template <typename T> -T* SimpleDeserialize(const volatile void* input, - size_t input_size, - void* output, - size_t output_size) { - if (input_size < sizeof(T)) - return nullptr; - memcpy(output, const_cast<void*>(input), sizeof(T)); - - T* op = reinterpret_cast<T*>(output); - if (!op->IsValid()) - return nullptr; - // Type and skip were already read once, so could have been changed. - // Don't trust them and clobber them with something valid. - UpdateTypeAndSkip(op); - return op; -} - PaintOp* AnnotateOp::Deserialize(const volatile void* input, size_t input_size, void* output, @@ -793,7 +813,19 @@ PaintOp* ClipRectOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ClipRectOp)); - return SimpleDeserialize<ClipRectOp>(input, input_size, output, output_size); + ClipRectOp* op = new (output) ClipRectOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->rect); + helper.Read(&op->op); + helper.Read(&op->antialias); + if (!helper.valid() || !op->IsValid()) { + op->~ClipRectOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* ClipRRectOp::Deserialize(const volatile void* input, @@ -802,7 +834,19 @@ PaintOp* ClipRRectOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ClipRRectOp)); - return SimpleDeserialize<ClipRRectOp>(input, input_size, output, output_size); + ClipRRectOp* op = new (output) ClipRRectOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->rrect); + helper.Read(&op->op); + helper.Read(&op->antialias); + if (!helper.valid() || !op->IsValid()) { + op->~ClipRRectOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* ConcatOp::Deserialize(const volatile void* input, @@ -811,10 +855,17 @@ PaintOp* ConcatOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ConcatOp)); - auto* op = - SimpleDeserialize<ConcatOp>(input, input_size, output, output_size); - if (op) - PaintOpReader::FixupMatrixPostSerialization(&op->matrix); + ConcatOp* op = new (output) ConcatOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->matrix); + if (!helper.valid() || !op->IsValid()) { + op->~ConcatOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + PaintOpReader::FixupMatrixPostSerialization(&op->matrix); return op; } @@ -824,8 +875,17 @@ PaintOp* CustomDataOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(CustomDataOp)); - return SimpleDeserialize<CustomDataOp>(input, input_size, output, - output_size); + CustomDataOp* op = new (output) CustomDataOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->id); + if (!helper.valid() || !op->IsValid()) { + op->~CustomDataOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* DrawColorOp::Deserialize(const volatile void* input, @@ -834,7 +894,18 @@ PaintOp* DrawColorOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawColorOp)); - return SimpleDeserialize<DrawColorOp>(input, input_size, output, output_size); + DrawColorOp* op = new (output) DrawColorOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->color); + helper.Read(&op->mode); + if (!helper.valid() || !op->IsValid()) { + op->~DrawColorOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* DrawDRRectOp::Deserialize(const volatile void* input, @@ -1097,7 +1168,16 @@ PaintOp* NoopOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(NoopOp)); - return SimpleDeserialize<NoopOp>(input, input_size, output, output_size); + NoopOp* op = new (output) NoopOp; + + PaintOpReader helper(input, input_size, options); + if (!helper.valid() || !op->IsValid()) { + op->~NoopOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* RestoreOp::Deserialize(const volatile void* input, @@ -1106,7 +1186,16 @@ PaintOp* RestoreOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(RestoreOp)); - return SimpleDeserialize<RestoreOp>(input, input_size, output, output_size); + RestoreOp* op = new (output) RestoreOp; + + PaintOpReader helper(input, input_size, options); + if (!helper.valid() || !op->IsValid()) { + op->~RestoreOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* RotateOp::Deserialize(const volatile void* input, @@ -1115,7 +1204,17 @@ PaintOp* RotateOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(RotateOp)); - return SimpleDeserialize<RotateOp>(input, input_size, output, output_size); + RotateOp* op = new (output) RotateOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->degrees); + if (!helper.valid() || !op->IsValid()) { + op->~RotateOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* SaveOp::Deserialize(const volatile void* input, @@ -1124,7 +1223,16 @@ PaintOp* SaveOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SaveOp)); - return SimpleDeserialize<SaveOp>(input, input_size, output, output_size); + SaveOp* op = new (output) SaveOp; + + PaintOpReader helper(input, input_size, options); + if (!helper.valid() || !op->IsValid()) { + op->~SaveOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* SaveLayerOp::Deserialize(const volatile void* input, @@ -1152,8 +1260,18 @@ PaintOp* SaveLayerAlphaOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SaveLayerAlphaOp)); - return SimpleDeserialize<SaveLayerAlphaOp>(input, input_size, output, - output_size); + SaveLayerAlphaOp* op = new (output) SaveLayerAlphaOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->bounds); + helper.Read(&op->alpha); + if (!helper.valid() || !op->IsValid()) { + op->~SaveLayerAlphaOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* ScaleOp::Deserialize(const volatile void* input, @@ -1163,7 +1281,18 @@ PaintOp* ScaleOp::Deserialize(const volatile void* input, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ScaleOp)); - return SimpleDeserialize<ScaleOp>(input, input_size, output, output_size); + ScaleOp* op = new (output) ScaleOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->sx); + helper.Read(&op->sy); + if (!helper.valid() || !op->IsValid()) { + op->~ScaleOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* SetMatrixOp::Deserialize(const volatile void* input, @@ -1172,10 +1301,17 @@ PaintOp* SetMatrixOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SetMatrixOp)); - auto* op = - SimpleDeserialize<SetMatrixOp>(input, input_size, output, output_size); - if (op) - PaintOpReader::FixupMatrixPostSerialization(&op->matrix); + SetMatrixOp* op = new (output) SetMatrixOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->matrix); + if (!helper.valid() || !op->IsValid()) { + op->~SetMatrixOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + PaintOpReader::FixupMatrixPostSerialization(&op->matrix); return op; } @@ -1185,7 +1321,17 @@ PaintOp* SetNodeIdOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SetNodeIdOp)); - return SimpleDeserialize<SetNodeIdOp>(input, input_size, output, output_size); + SetNodeIdOp* op = new (output) SetNodeIdOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->node_id); + if (!helper.valid() || !op->IsValid()) { + op->~SetNodeIdOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } PaintOp* TranslateOp::Deserialize(const volatile void* input, @@ -1194,7 +1340,18 @@ PaintOp* TranslateOp::Deserialize(const volatile void* input, size_t output_size, const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(TranslateOp)); - return SimpleDeserialize<TranslateOp>(input, input_size, output, output_size); + TranslateOp* op = new (output) TranslateOp; + + PaintOpReader helper(input, input_size, options); + helper.Read(&op->dx); + helper.Read(&op->dy); + if (!helper.valid() || !op->IsValid()) { + op->~TranslateOp(); + return nullptr; + } + + UpdateTypeAndSkip(op); + return op; } void AnnotateOp::Raster(const AnnotateOp* op, diff --git a/chromium/cc/paint/paint_op_buffer.h b/chromium/cc/paint/paint_op_buffer.h index d327fe6fc3f..24d16fddd4d 100644 --- a/chromium/cc/paint/paint_op_buffer.h +++ b/chromium/cc/paint/paint_op_buffer.h @@ -48,6 +48,7 @@ class CC_PAINT_EXPORT ThreadsafeMatrix : public SkMatrix { explicit ThreadsafeMatrix(const SkMatrix& matrix) : SkMatrix(matrix) { (void)getType(); } + ThreadsafeMatrix() { (void)getType(); } }; class CC_PAINT_EXPORT ThreadsafePath : public SkPath { @@ -401,6 +402,9 @@ class CC_PAINT_EXPORT ClipRectOp final : public PaintOp { SkRect rect; SkClipOp op; bool antialias; + + private: + ClipRectOp() : PaintOp(kType) {} }; class CC_PAINT_EXPORT ClipRRectOp final : public PaintOp { @@ -419,6 +423,9 @@ class CC_PAINT_EXPORT ClipRRectOp final : public PaintOp { SkRRect rrect; SkClipOp op; bool antialias; + + private: + ClipRRectOp() : PaintOp(kType) {} }; class CC_PAINT_EXPORT ConcatOp final : public PaintOp { @@ -433,6 +440,9 @@ class CC_PAINT_EXPORT ConcatOp final : public PaintOp { HAS_SERIALIZATION_FUNCTIONS(); ThreadsafeMatrix matrix; + + private: + ConcatOp() : PaintOp(kType) {} }; class CC_PAINT_EXPORT CustomDataOp final : public PaintOp { @@ -448,6 +458,9 @@ class CC_PAINT_EXPORT CustomDataOp final : public PaintOp { // Stores user defined id as a placeholder op. uint32_t id; + + private: + CustomDataOp() : PaintOp(kType) {} }; class CC_PAINT_EXPORT DrawColorOp final : public PaintOp { @@ -465,6 +478,9 @@ class CC_PAINT_EXPORT DrawColorOp final : public PaintOp { SkColor color; SkBlendMode mode; + + private: + DrawColorOp() : PaintOp(kType) {} }; class CC_PAINT_EXPORT DrawDRRectOp final : public PaintOpWithFlags { @@ -808,6 +824,9 @@ class CC_PAINT_EXPORT RotateOp final : public PaintOp { HAS_SERIALIZATION_FUNCTIONS(); SkScalar degrees; + + private: + RotateOp() : PaintOp(kType) {} }; class CC_PAINT_EXPORT SaveOp final : public PaintOp { @@ -857,6 +876,9 @@ class CC_PAINT_EXPORT SaveLayerAlphaOp final : public PaintOp { SkRect bounds; uint8_t alpha; + + private: + SaveLayerAlphaOp() : PaintOp(kType) {} }; class CC_PAINT_EXPORT ScaleOp final : public PaintOp { @@ -896,6 +918,9 @@ class CC_PAINT_EXPORT SetMatrixOp final : public PaintOp { HAS_SERIALIZATION_FUNCTIONS(); ThreadsafeMatrix matrix; + + private: + SetMatrixOp() : PaintOp(kType) {} }; class CC_PAINT_EXPORT SetNodeIdOp final : public PaintOp { @@ -910,6 +935,9 @@ class CC_PAINT_EXPORT SetNodeIdOp final : public PaintOp { HAS_SERIALIZATION_FUNCTIONS(); int node_id; + + private: + SetNodeIdOp() : PaintOp(kType) {} }; class CC_PAINT_EXPORT TranslateOp final : public PaintOp { @@ -925,6 +953,9 @@ class CC_PAINT_EXPORT TranslateOp final : public PaintOp { SkScalar dx; SkScalar dy; + + private: + TranslateOp() : PaintOp(kType) {} }; #undef HAS_SERIALIZATION_FUNCTIONS diff --git a/chromium/cc/paint/paint_op_reader.h b/chromium/cc/paint/paint_op_reader.h index 9de213ec7f0..e20611747cb 100644 --- a/chromium/cc/paint/paint_op_reader.h +++ b/chromium/cc/paint/paint_op_reader.h @@ -99,6 +99,15 @@ class CC_PAINT_EXPORT PaintOpReader { } *quality = static_cast<SkFilterQuality>(value); } + void Read(SkBlendMode* blend_mode) { + uint8_t value = 0u; + Read(&value); + if (value > static_cast<uint8_t>(SkBlendMode::kLastMode)) { + SetInvalid(); + return; + } + *blend_mode = static_cast<SkBlendMode>(value); + } void Read(bool* data) { uint8_t value = 0u; Read(&value); diff --git a/chromium/cc/paint/paint_op_writer.h b/chromium/cc/paint/paint_op_writer.h index 187d697796b..a05ae667af6 100644 --- a/chromium/cc/paint/paint_op_writer.h +++ b/chromium/cc/paint/paint_op_writer.h @@ -75,6 +75,9 @@ class CC_PAINT_EXPORT PaintOpWriter { void Write(SkFilterQuality filter_quality) { Write(static_cast<uint8_t>(filter_quality)); } + void Write(SkBlendMode blend_mode) { + Write(static_cast<uint8_t>(blend_mode)); + } void Write(bool data) { Write(static_cast<uint8_t>(data)); } // Aligns the memory to the given alignment. |