Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions flutter_angle/example/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
5 changes: 2 additions & 3 deletions flutter_angle/lib/flutter_angle.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
library flutter_angle;

export 'desktop/index.dart'
if (dart.library.js_interop) 'webgl/index.dart';
export 'desktop/index.dart' if (dart.library.js_interop) 'webgl/index.dart';
export 'shared/webgl.dart';
export 'shared/options.dart';
export 'shared/classes.dart';
export 'shared/classes.dart';
26 changes: 24 additions & 2 deletions flutter_angle/windows/flutter_angle_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,22 @@ namespace {
return;
}

// Input validation to prevent crashes
const int MAX_TEXTURE_SIZE = 8192;
if (width <= 0 || height <= 0) {
result->Error("Invalid texture dimensions", "Width and height must be positive");
return;
}
if (width > MAX_TEXTURE_SIZE || height > MAX_TEXTURE_SIZE) {
result->Error("Texture too large", "Width and height must be less than " + std::to_string(MAX_TEXTURE_SIZE));
return;
}
// Check for potential integer overflow
if (width > INT_MAX / height / 4) {
result->Error("Texture too large", "Texture dimensions would cause integer overflow");
return;
}

std::unique_ptr<FlutterGLTexture> flutterGLTexture;

try{
Expand All @@ -147,8 +163,14 @@ namespace {
renderers.insert(RendererMap::value_type(textureId, std::move(flutterGLTexture)));
renderers[textureId]->createTexture(result);
}
catch (OpenGLException ex){
result->Error(ex.message + ':' + std::to_string(ex.error));
catch (const OpenGLException& ex){
result->Error(std::string(ex.message) + ":" + std::to_string(ex.error));
}
catch (const std::exception& ex) {
result->Error("Standard exception", ex.what());
}
catch (...) {
result->Error("Unknown exception", "An unknown exception occurred during texture creation");
}
}
else if (method_call.method_name().compare("updateTexture") == 0 || method_call.method_name().compare("textureFrameAvailable") == 0) {
Expand Down
93 changes: 89 additions & 4 deletions flutter_angle/windows/flutter_gl_texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,67 @@ EGLInfo FlutterGLTexture::initOpenGL(std::unique_ptr<flutter::MethodResult<flutt
}

void FlutterGLTexture::changeSize(int setWidth, int setHeight, std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>>& result) {
// Input validation to prevent buffer overrun
const int MAX_TEXTURE_SIZE = 8192; // Reasonable maximum texture size
if (setWidth <= 0 || setHeight <= 0) {
result->Error("Invalid texture dimensions", "Width and height must be positive");
return;
}
if (setWidth > MAX_TEXTURE_SIZE || setHeight > MAX_TEXTURE_SIZE) {
result->Error("Texture too large", "Width and height must be less than " + std::to_string(MAX_TEXTURE_SIZE));
return;
}

// Check for integer overflow before multiplication
if (setWidth > INT_MAX / setHeight / 4) {
result->Error("Texture too large", "Texture dimensions would cause integer overflow");
return;
}

if (setWidth == structure.width && setHeight == structure.height && didStart) {
return;
}
if(structure.useBuffer){
// Update internal dimensions for buffer mode as well
structure.width = setWidth;
structure.height = setHeight;

int64_t size = setWidth * setHeight * 4;
pixels.reset(new uint8_t[size]);

// Additional safety check
if (size <= 0 || size > SIZE_MAX) {
result->Error("Invalid buffer size", "Calculated buffer size is invalid");
return;
}

try {
pixels.reset(new uint8_t[size]);
} catch (const std::bad_alloc&) {
result->Error("Memory allocation failed", "Failed to allocate memory for texture buffer");
return;
}

// Validate pixelBuffer is initialized
if (!pixelBuffer) {
result->Error("Pixel buffer not initialized", "Pixel buffer is null");
return;
}

pixelBuffer->buffer = pixels.get();
pixelBuffer->width = setWidth;
pixelBuffer->height = setHeight;
memset(pixels.get(), 0x00, size);

// Recreate FBO/RBO to match new size to avoid partial reads/flicker
if (textures.rboId != 0) {
glDeleteRenderbuffers(1, &textures.rboId);
textures.rboId = 0;
}
if (textures.fboId != 0) {
glDeleteFramebuffers(1, &textures.fboId);
textures.fboId = 0;
}
setupOpenGLResources();
if(didStart){
/// we send back the context so that the Dart side can create a linked context.
auto response = flutter::EncodableValue(flutter::EncodableMap{
Expand Down Expand Up @@ -306,14 +356,14 @@ void FlutterGLTexture::setupOpenGLResources(){
auto error = glGetError();
if (error != GL_NO_ERROR){
std::cerr << "GlError while allocating Renderbuffer" << error << std::endl;
throw new OpenGLException("GlError while allocating Renderbuffer", error);
throw OpenGLException("GlError while allocating Renderbuffer", error);
}
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,rbo);

auto frameBufferCheck = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (frameBufferCheck != GL_FRAMEBUFFER_COMPLETE){
std::cerr << "Framebuffer error" << frameBufferCheck << std::endl;
throw new OpenGLException("Framebuffer Error while creating Texture", frameBufferCheck);
throw OpenGLException("Framebuffer Error while creating Texture", frameBufferCheck);
}

error = glGetError();
Expand All @@ -329,7 +379,6 @@ void FlutterGLTexture::createTexture(std::unique_ptr<flutter::MethodResult<flutt
if(structure.useBuffer){
pixelBuffer = std::make_unique<FlutterDesktopPixelBuffer>();
changeSize(structure.width,structure.height,result);
setupOpenGLResources();
}

didStart = true;
Expand All @@ -349,8 +398,44 @@ void FlutterGLTexture::createTexture(std::unique_ptr<flutter::MethodResult<flutt

void FlutterGLTexture::textureFrameAvailable(std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>>& result){
if(structure.useBuffer){
// Validate pixelBuffer and its buffer before use
if (!pixelBuffer) {
result->Error("Pixel buffer not initialized", "Pixel buffer is null");
return;
}
if (!pixelBuffer->buffer) {
result->Error("Pixel buffer data not allocated", "Pixel buffer data is null");
return;
}
if (pixelBuffer->width <= 0 || pixelBuffer->height <= 0) {
result->Error("Invalid pixel buffer dimensions", "Pixel buffer dimensions are invalid");
return;
}

// Check for potential buffer overrun
int64_t requiredSize = pixelBuffer->width * pixelBuffer->height * 4;
if (requiredSize <= 0 || requiredSize > SIZE_MAX) {
result->Error("Invalid buffer size for read operation", "Calculated buffer size is invalid");
return;
}

glBindFramebuffer(GL_FRAMEBUFFER, textures.fboId);

// Check for OpenGL errors before read operation
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
result->Error("OpenGL error before readPixels", "OpenGL error: " + std::to_string(error));
return;
}

glReadPixels(0, 0, (GLsizei)pixelBuffer->width, (GLsizei)pixelBuffer->height, GL_RGBA, GL_UNSIGNED_BYTE, (void*)pixelBuffer->buffer);

// Check for OpenGL errors after read operation
error = glGetError();
if (error != GL_NO_ERROR) {
result->Error("OpenGL error during readPixels", "OpenGL error: " + std::to_string(error));
return;
}
}
textureRegistrar->MarkTextureFrameAvailable(textureId);
result->Success();
Expand Down
Binary file added flutter_angle_crash_fix.patch
Binary file not shown.
10 changes: 10 additions & 0 deletions h_fix.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
67707ff (HEAD -> main, origin/main, origin/HEAD) updates for pub dev
c113385 Fixed ANGLE spamming issue on debug
c89d398 Fixed binding error
c96e25a added antialias to web
de96ed3 pub dev updates
9570127 Fixed web release bug
b36beeb making web consistent and looking for memory leaks
0654066 updates to fix Linux artifacts
815652a removed glew
b1df2ce update for pub dev