diff --git a/include/mbgl/layermanager/circle_layer_factory.hpp b/include/mbgl/layermanager/circle_layer_factory.hpp index 11b4a6086..c0bf921ef 100644 --- a/include/mbgl/layermanager/circle_layer_factory.hpp +++ b/include/mbgl/layermanager/circle_layer_factory.hpp @@ -11,7 +11,7 @@ protected: const style::conversion::Convertible& value) noexcept final; std::unique_ptr createLayout(const LayoutParameters& parameters, std::unique_ptr tileLayer, - const std::vector>& group) noexcept final; + const std::vector>& group) final; std::unique_ptr createRenderLayer(Immutable) noexcept final; }; diff --git a/include/mbgl/layermanager/fill_extrusion_layer_factory.hpp b/include/mbgl/layermanager/fill_extrusion_layer_factory.hpp index 4d65140c3..4ca4bf985 100644 --- a/include/mbgl/layermanager/fill_extrusion_layer_factory.hpp +++ b/include/mbgl/layermanager/fill_extrusion_layer_factory.hpp @@ -11,7 +11,7 @@ protected: const style::conversion::Convertible& value) noexcept final; std::unique_ptr createLayout(const LayoutParameters&, std::unique_ptr, - const std::vector>&) noexcept final; + const std::vector>&) final; std::unique_ptr createRenderLayer(Immutable) noexcept final; }; diff --git a/include/mbgl/layermanager/fill_layer_factory.hpp b/include/mbgl/layermanager/fill_layer_factory.hpp index 594ccf194..b02a190fc 100644 --- a/include/mbgl/layermanager/fill_layer_factory.hpp +++ b/include/mbgl/layermanager/fill_layer_factory.hpp @@ -11,7 +11,7 @@ protected: const style::conversion::Convertible& value) noexcept final; std::unique_ptr createLayout(const LayoutParameters&, std::unique_ptr, - const std::vector>&) noexcept final; + const std::vector>&) final; std::unique_ptr createRenderLayer(Immutable) noexcept final; }; diff --git a/include/mbgl/layermanager/layer_factory.hpp b/include/mbgl/layermanager/layer_factory.hpp index b58136273..480f74d86 100644 --- a/include/mbgl/layermanager/layer_factory.hpp +++ b/include/mbgl/layermanager/layer_factory.hpp @@ -38,7 +38,7 @@ public: /// Returns a new Layout instance on success call; returns `nullptr` otherwise. virtual std::unique_ptr createLayout(const LayoutParameters&, std::unique_ptr, - const std::vector>&) noexcept; + const std::vector>&); protected: std::optional getSource(const style::conversion::Convertible& value) const noexcept; diff --git a/include/mbgl/layermanager/symbol_layer_factory.hpp b/include/mbgl/layermanager/symbol_layer_factory.hpp index 8aacca771..326f9d07a 100644 --- a/include/mbgl/layermanager/symbol_layer_factory.hpp +++ b/include/mbgl/layermanager/symbol_layer_factory.hpp @@ -11,7 +11,7 @@ protected: const style::conversion::Convertible& value) noexcept final; std::unique_ptr createLayout(const LayoutParameters& parameters, std::unique_ptr tileLayer, - const std::vector>& group) noexcept final; + const std::vector>& group) final; std::unique_ptr createRenderLayer(Immutable) noexcept final; }; diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 371c1dad0..5ba45e14d 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -4,6 +4,8 @@ MapLibre welcomes participation and contributions from everyone. Please read [`C ## main +- Fix reported [crash](https://github.com/maplibre/maplibre-native/issues/2678) when feature contains invalid UTF-8 data. + ## 6.5.3 - Disabled iOS 14 metal options ([#2620](https://github.com/maplibre/maplibre-native/pull/2620)). diff --git a/src/mbgl/layermanager/circle_layer_factory.cpp b/src/mbgl/layermanager/circle_layer_factory.cpp index e92b0a536..509c2e7e3 100644 --- a/src/mbgl/layermanager/circle_layer_factory.cpp +++ b/src/mbgl/layermanager/circle_layer_factory.cpp @@ -18,10 +18,9 @@ std::unique_ptr CircleLayerFactory::createLayer(const std::string& return std::unique_ptr(source ? new (std::nothrow) style::CircleLayer(id, *source) : nullptr); } -std::unique_ptr CircleLayerFactory::createLayout( - const LayoutParameters& parameters, - std::unique_ptr layer, - const std::vector>& group) noexcept { +std::unique_ptr CircleLayerFactory::createLayout(const LayoutParameters& parameters, + std::unique_ptr layer, + const std::vector>& group) { return std::unique_ptr(new (std::nothrow) CircleLayout(parameters.bucketParameters, group, std::move(layer))); } diff --git a/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp b/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp index cf757022f..b9e8f3f68 100644 --- a/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp +++ b/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp @@ -20,7 +20,7 @@ std::unique_ptr FillExtrusionLayerFactory::createLayer( std::unique_ptr FillExtrusionLayerFactory::createLayout( const LayoutParameters& parameters, std::unique_ptr layer, - const std::vector>& group) noexcept { + const std::vector>& group) { using namespace style; using LayoutType = PatternLayout; return std::unique_ptr(new (std::nothrow) diff --git a/src/mbgl/layermanager/fill_layer_factory.cpp b/src/mbgl/layermanager/fill_layer_factory.cpp index f7faf3ac0..2bc931169 100644 --- a/src/mbgl/layermanager/fill_layer_factory.cpp +++ b/src/mbgl/layermanager/fill_layer_factory.cpp @@ -17,10 +17,9 @@ std::unique_ptr FillLayerFactory::createLayer(const std::string& i return std::unique_ptr(source ? new (std::nothrow) style::FillLayer(id, *source) : nullptr); } -std::unique_ptr FillLayerFactory::createLayout( - const LayoutParameters& parameters, - std::unique_ptr layer, - const std::vector>& group) noexcept { +std::unique_ptr FillLayerFactory::createLayout(const LayoutParameters& parameters, + std::unique_ptr layer, + const std::vector>& group) { using namespace style; using LayoutTypeUnsorted = PatternLayout; using LayoutTypeSorted = diff --git a/src/mbgl/layermanager/layer_factory.cpp b/src/mbgl/layermanager/layer_factory.cpp index 8c20f5907..4e41c0975 100644 --- a/src/mbgl/layermanager/layer_factory.cpp +++ b/src/mbgl/layermanager/layer_factory.cpp @@ -33,7 +33,7 @@ std::unique_ptr LayerFactory::createBucket(const BucketParameters&, std::unique_ptr LayerFactory::createLayout(const LayoutParameters&, std::unique_ptr, - const std::vector>&) noexcept { + const std::vector>&) { assert(false); return nullptr; } diff --git a/src/mbgl/layermanager/symbol_layer_factory.cpp b/src/mbgl/layermanager/symbol_layer_factory.cpp index 3c4d2c4d2..2ac028a82 100644 --- a/src/mbgl/layermanager/symbol_layer_factory.cpp +++ b/src/mbgl/layermanager/symbol_layer_factory.cpp @@ -17,10 +17,9 @@ std::unique_ptr SymbolLayerFactory::createLayer(const std::string& return std::unique_ptr(source ? new (std::nothrow) style::SymbolLayer(id, *source) : nullptr); } -std::unique_ptr SymbolLayerFactory::createLayout( - const LayoutParameters& parameters, - std::unique_ptr tileLayer, - const std::vector>& group) noexcept { +std::unique_ptr SymbolLayerFactory::createLayout(const LayoutParameters& parameters, + std::unique_ptr tileLayer, + const std::vector>& group) { return std::unique_ptr( new (std::nothrow) SymbolLayout(parameters.bucketParameters, group, std::move(tileLayer), parameters)); } diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 454740266..7051712f0 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -156,11 +156,19 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters, } else if (textTransform == TextTransformType::Lowercase) { u8string = platform::lowercase(u8string); } - - ft.formattedText->addTextSection(applyArabicShaping(util::convertUTF8ToUTF16(u8string)), - section.fontScale ? *section.fontScale : 1.0, - section.fontStack ? *section.fontStack : baseFontStack, - section.textColor); + try { + ft.formattedText->addTextSection(applyArabicShaping(util::convertUTF8ToUTF16(u8string)), + section.fontScale ? *section.fontScale : 1.0, + section.fontStack ? *section.fontStack : baseFontStack, + section.textColor); + } catch (...) { + mbgl::Log::Error( + mbgl::Event::ParseTile, + "Encountered section with invalid UTF-8 in tile, source: " + sourceLayer->getName() + + " z: " + std::to_string(canonicalID.z) + " x: " + std::to_string(canonicalID.x) + + " y: " + std::to_string(canonicalID.y)); + continue; // skip section + } } else { layoutParameters.imageDependencies.emplace(section.image->id(), ImageType::Icon); ft.formattedText->addImageSection(section.image->id()); diff --git a/test/fixtures/map/invalid_utf8/invalidutf8feature.mvt b/test/fixtures/map/invalid_utf8/invalidutf8feature.mvt new file mode 100644 index 000000000..3db586418 Binary files /dev/null and b/test/fixtures/map/invalid_utf8/invalidutf8feature.mvt differ diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp index 856fd2999..f271ce272 100644 --- a/test/map/map.test.cpp +++ b/test/map/map.test.cpp @@ -1640,3 +1640,47 @@ TEST(Map, StencilOverflow) { // TODO: confirm that the stencil masking actually worked } + +TEST(Map, InvalidUTF8InTile) { + FixtureLog log; + + MapTest<> test{1, MapMode::Continuous}; + + test.fileSource->tileResponse = [&](const Resource&) { + Response result; + result.data = std::make_shared( + util::read_file("test/fixtures/map/invalid_utf8/invalidutf8feature.mvt")); + return result; + }; + test.fileSource->glyphsResponse = makeResponse("glyphs.pbf", true); + + test.map.jumpTo(CameraOptions().withZoom(11.0)); + test.map.getStyle().loadJSON(R"STYLE({ + "version": 8, + "sources": { + "invalidutf8": { + "type": "vector", + "tiles": ["http://example.com/{z}-{x}-{y}.vector.pbf"] + } + }, + "layers": [{ + "id": "mountain_peak", + "type": "symbol", + "source": "invalidutf8", + "source-layer": "points", + "layout": { + "text-field": "{name}" + } + }] + })STYLE"); + + test.observer.didFinishLoadingMapCallback = [&]() { + test.observer.didFinishRenderingFrameCallback = [&](MapObserver::RenderFrameStatus status) { + if (!status.needsRepaint) { + test.runLoop.stop(); + } + }; + }; + + test.runLoop.run(); +}