flarum / framework

Simple forum software for building great communities.
http://flarum.org/
6.3k stars 835 forks source link

Unable to encode data to JSON in Zend\Diactoros\Response\JsonResponse: Malformed UTF-8 characters, possibly incorrectly encoded #1452

Closed gwillem closed 3 years ago

gwillem commented 6 years ago

Explanation

A (Vietnamese) FreeFlarum user bricked (part of) their forum by submitting a specific post. As soon as the post is rendered in discussion or tag overview:

InvalidArgumentException thrown with message "Unable to encode data to JSON in Zend\Diactoros\Response\JsonResponse: Malformed UTF-8 characters, possibly incorrectly encoded"

Stacktrace:
#42 InvalidArgumentException in /public/vendor/zendframework/zend-diactoros/src/Response/JsonResponse.php:155
#41 Zend\Diactoros\Response\JsonResponse:jsonEncode in /public/vendor/zendframework/zend-diactoros/src/Response/JsonResponse.php:73
#40 Zend\Diactoros\Response\JsonResponse:__construct in /public/vendor/flarum/core/src/Api/JsonApiResponse.php:29
#39 Flarum\Api\JsonApiResponse:__construct in /public/vendor/flarum/core/src/Api/Controller/AbstractSerializeController.php:112
#38 Flarum\Api\Controller\AbstractSerializeController:handle in /public/vendor/flarum/core/src/Api/Client.php:69
#37 Flarum\Api\Client:send in /public/vendor/flarum/core/src/Forum/Controller/DiscussionController.php:105
#36 Flarum\Forum\Controller\DiscussionController:getDocument in /public/vendor/flarum/core/src/Forum/Controller/DiscussionController.php:64
#35 Flarum\Forum\Controller\DiscussionController:getView in /public/vendor/flarum/core/src/Http/Controller/AbstractWebAppController.php:37
#34 Flarum\Http\Controller\AbstractWebAppController:render in /public/vendor/flarum/core/src/Http/Controller/AbstractHtmlController.php:25
#33 Flarum\Http\Controller\AbstractHtmlController:handle in /public/vendor/flarum/core/src/Http/Handler/ControllerRouteHandler.php:53
#32 Flarum\Http\Handler\ControllerRouteHandler:__invoke in /public/vendor/flarum/core/src/Http/Middleware/DispatchRoute.php:69
#31 Flarum\Http\Middleware\DispatchRoute:__invoke in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:212
#30 Zend\Stratigility\Dispatch:dispatchCallableMiddleware in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:88
#29 Zend\Stratigility\Dispatch:__invoke in /public/vendor/zendframework/zend-stratigility/src/Next.php:160
#28 Zend\Stratigility\Next:__invoke in /public/vendor/flarum/core/src/Http/Middleware/SetLocale.php:51
#27 Flarum\Http\Middleware\SetLocale:__invoke in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:212
#26 Zend\Stratigility\Dispatch:dispatchCallableMiddleware in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:88
#25 Zend\Stratigility\Dispatch:__invoke in /public/vendor/zendframework/zend-stratigility/src/Next.php:160
#24 Zend\Stratigility\Next:__invoke in /public/vendor/flarum/core/src/Http/Middleware/AuthenticateWithSession.php:36
#23 Flarum\Http\Middleware\AuthenticateWithSession:__invoke in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:212
#22 Zend\Stratigility\Dispatch:dispatchCallableMiddleware in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:88
#21 Zend\Stratigility\Dispatch:__invoke in /public/vendor/zendframework/zend-stratigility/src/Next.php:160
#20 Zend\Stratigility\Next:__invoke in /public/vendor/flarum/core/src/Http/Middleware/RememberFromCookie.php:39
#19 Flarum\Http\Middleware\RememberFromCookie:__invoke in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:212
#18 Zend\Stratigility\Dispatch:dispatchCallableMiddleware in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:88
#17 Zend\Stratigility\Dispatch:__invoke in /public/vendor/zendframework/zend-stratigility/src/Next.php:160
#16 Zend\Stratigility\Next:__invoke in /public/vendor/flarum/core/src/Http/Middleware/StartSession.php:48
#15 Flarum\Http\Middleware\StartSession:__invoke in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:212
#14 Zend\Stratigility\Dispatch:dispatchCallableMiddleware in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:88
#13 Zend\Stratigility\Dispatch:__invoke in /public/vendor/zendframework/zend-stratigility/src/Next.php:160
#12 Zend\Stratigility\Next:__invoke in /public/vendor/flarum/core/src/Http/Middleware/ParseJsonBody.php:31
#11 Flarum\Http\Middleware\ParseJsonBody:__invoke in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:212
#10 Zend\Stratigility\Dispatch:dispatchCallableMiddleware in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:88
#9 Zend\Stratigility\Dispatch:__invoke in /public/vendor/zendframework/zend-stratigility/src/Next.php:160
#8 Zend\Stratigility\Next:__invoke in /public/vendor/flarum/core/src/Http/Middleware/HandleErrors.php:61
#7 Flarum\Http\Middleware\HandleErrors:__invoke in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:212
#6 Zend\Stratigility\Dispatch:dispatchCallableMiddleware in /public/vendor/zendframework/zend-stratigility/src/Dispatch.php:88
#5 Zend\Stratigility\Dispatch:__invoke in /public/vendor/zendframework/zend-stratigility/src/Next.php:160
#4 Zend\Stratigility\Next:__invoke in /public/vendor/zendframework/zend-stratigility/src/MiddlewarePipe.php:111
#3 Zend\Stratigility\MiddlewarePipe:__invoke in /public/vendor/flarum/core/src/Http/AbstractServer.php:55
#2 Flarum\Http\AbstractServer:__invoke in /public/vendor/zendframework/zend-diactoros/src/Server.php:157
#1 Zend\Diactoros\Server:listen in /public/vendor/flarum/core/src/Http/AbstractServer.php:36
#0 Flarum\Http\AbstractServer:listen in /public/index.php:16

The problem is reproducible, however I cannot establish if there is invalid UTF-8. Python's JSON renderer does not have any problems with it. I also tried copy-pasting the post title & content from the database to another forum on the same server, but that did not yield an exception.

Technical details

Flarum info

Flarum core 0.1.0-beta.7
PHP 7.0.30-0ubuntu0.16.04.1
Loaded extensions: Core, date, libxml, openssl, pcre, zlib, filter, hash, pcntl, Reflection, SPL, session, standard, mysqlnd, PDO, xml, calendar, ctype, curl, dom, mbstring, fileinfo, ftp, gd, gettext, iconv, json, exif, mysqli, pdo_mysql, Phar, posix, readline, shmop, SimpleXML, sockets, sysvmsg, sysvsem, sysvshm, tokenizer, wddx, xmlreader, xmlwriter, xsl, zip, Zend OPcache
EXT flarum-approval v0.1.0-beta.7
EXT s9e-autoimage 1.0.2
EXT s9e-autovideo 1.0.0
EXT flarum-bbcode v0.1.0-beta.5
EXT flarum-english v0.1.0-beta.7
EXT flarum-auth-facebook v0.1.0-beta.6
EXT flagrow-byobu 0.1.1
EXT flagrow-split 0.2
EXT flarum-flags v0.1.0-beta.7
EXT flarum-lock v0.1.0-beta.7
EXT flarum-markdown v0.1.0-beta.5
EXT xengine-markdown-editor 1.3.1
EXT s9e-mediaembed 0.3.2
EXT flarum-mentions v0.1.0-beta.7
EXT antoinefr-money 0.5.0
EXT xengine-signature 0.1.2
EXT flarum-sticky v0.1.0-beta.7
EXT flarum-subscriptions v0.1.0-beta.6
EXT jordanjay29-summaries 0.2.0
EXT flarum-suspend v0.1.0-beta.7
EXT flarum-tags v0.1.0-beta.8
Base URL: https://thewhitex.freeflarum.com
Installation path: /data/host/thewhitex/public

Apparently it was reported by other users of UTF-8 languages:

https://forum.flarumchina.org/d/411/19 http://discuss.flarum.org.cn/d/3536

How to debug?

franzliedke commented 6 years ago

Please isolate which attribute is causing the problems, by removing them one by one from the serializer that is creating the JSON. Then, please let us know what is the type / charset of the relevant database column.

gwillem commented 6 years ago

I'm afraid my PHP skills are too limited to isolate the serializer. Could you give me a few pointers?

DB:

+--------------------------+----------------------+
| @@character_set_database | @@collation_database |
+--------------------------+----------------------+
| utf8mb4                  | utf8mb4_general_ci   |
+--------------------------+----------------------+
luceos commented 6 years ago

Feel free to post the full payload if you have it.

franzliedke commented 6 years ago

@gwillem We need the post / discussion data to be able to make any progress here.

gwillem commented 6 years ago

Can I share the DB dump somewhere privately? Update: credentials shared with @franzliedke on Discord.

franzliedke commented 6 years ago

Thank you @gwillem! I was able to reproduce the problem with the data you shared. Now for isolating the exact problem...

franzliedke commented 6 years ago

I have tracked this down to TextFormatter, hehe. Unfortunately, I haven't been able to reduce it down to a very short example snippet that would trigger the error as well. But I have a (very long) example post that does.

@JoshyPHP Would you be interested in this example post? I could share it with you privately (on Discord?) to debug on a Flarum instance?

franzliedke commented 6 years ago

(The problem appears when JSON encoding the post's content_html attribute (which is its content sent through TextFormatter).

Down in the depths of the zend-diactoros library, we serialize the JSON with json_encode($content_html, 79). That returns boolean false in this case. json_encode($content, 79) works, though, which makes me think the problem is something TextFormatter does to the data.

JoshyPHP commented 6 years ago

@franzliedke If you have the HTML, can you make a reduced case where json_encode() returns false and attach it here?

nowfalsalahudeen commented 6 years ago

change data type 'text' to 'long text' in content field of 'post' table (flarum db). this fixed my issue. The column used to be TEXT, which is limited to 65535 characters. but LONG TEXT does the job very well if u r make long text size post

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. We do this to keep the amount of open issues to a manageable minimum. In any case, thanks for taking an interest in this software and contributing by opening the issue in the first place!

askvortsov1 commented 3 years ago

Let's just catch errors when rendering posts, and display some error message instead that contains the post ID, and logs the error message to system logs? IMO, anything that could brick the forum should be avoided at all costs.