특정 메시지를 채팅으로 보낼 수 없음

어떤 이유인지 모르겠지만, 두 개의 서로 다른 비-Meta 포럼에서 이 정확한 메시지를 채팅으로 전송할 수 없습니다:

???
```
firepup650@firepi:~/projects/python/bitbot $ sudo journalctl -fu h-bitbot
Sep 16 18:21:33 firepi systemd[1]: Starting h-bitbot.service - 9pfs's bitbot...
Sep 16 18:21:33 firepi systemd[1]: Started h-bitbot.service - 9pfs's bitbot.
Sep 16 18:21:34 firepi systemd[1]: h-bitbot.service: Main process exited, code=exited, status=1/FAILURE
Sep 16 18:21:34 firepi systemd[1]: h-bitbot.service: Failed with result 'exit-code'.
Sep 16 18:21:34 firepi systemd[1]: h-bitbot.service: Consumed 1.157s CPU time, no IP traffic.
Sep 16 18:21:39 firepi systemd[1]: h-bitbot.service: Scheduled restart job, restart counter is at 84.
Sep 16 18:21:39 firepi systemd[1]: Stopped h-bitbot.service - 9pfs's bitbot.
Sep 16 18:21:39 firepi systemd[1]: h-bitbot.service: Consumed 1.157s CPU time, no IP traffic.
Sep 16 18:21:39 firepi systemd[1]: Starting h-bitbot.service - 9pfs's bitbot...
Sep 16 18:21:39 firepi systemd[1]: Started h-bitbot.service - 9pfs's bitbot.
Sep 16 18:21:42 firepi systemd[1]: h-bitbot.service: Main process exited, code=exited, status=1/FAILURE
```

첫 번째 줄의 ???를 제거하거나, 해당 로그 스니펫의 마지막 줄을 제거하면 정상적으로 전송됩니다.

어떤 이유인지 모르겠지만, Meta에서는 이를 재현할 수 없습니다.

https://forum.obl.ong/ 와 https://amcforum.wiki/ 에서 모두 오류가 발생하며, 500 오류를 유발합니다. AMC의 로그는 다음과 같습니다:

좀 긴 로그
Message (28 copies reported)

Failed to handle exception in exception app middleware : ActiveRecord::ValueTooLong : PG::StringDataRightTruncation: ERROR:  value too long for type character varying(1000)


Backtrace

rack-mini-profiler-3.3.1/lib/patches/db/pg.rb:72:in `exec_params'
rack-mini-profiler-3.3.1/lib/patches/db/pg.rb:72:in `exec_params'
activerecord-7.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:894:in `block (2 levels) in exec_no_cache'
activerecord-7.1.4/lib/active_record/connection_adapters/abstract_adapter.rb:1027:in `block in with_raw_connection'
activesupport-7.1.4/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
activerecord-7.1.4/lib/active_record/connection_adapters/abstract_adapter.rb:999:in `with_raw_connection'
activerecord-7.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:893:in `block in exec_no_cache'
activesupport-7.1.4/lib/active_support/notifications/instrumenter.rb:58:in `instrument'
activerecord-7.1.4/lib/active_record/connection_adapters/abstract_adapter.rb:1142:in `log'
activerecord-7.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:892:in `exec_no_cache'
activerecord-7.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:872:in `execute_and_clear'
activerecord-7.1.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:64:in `internal_exec_query'
activerecord-7.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:153:in `exec_insert'
activerecord-7.1.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:83:in `exec_insert'
activerecord-7.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:191:in `insert'
activerecord-7.1.4/lib/active_record/connection_adapters/abstract/query_cache.rb:25:in `insert'
activerecord-7.1.4/lib/active_record/persistence.rb:588:in `_insert_record'
activerecord-7.1.4/lib/active_record/persistence.rb:1252:in `_create_record'
activerecord-7.1.4/lib/active_record/counter_cache.rb:188:in `_create_record'
activerecord-7.1.4/lib/active_record/locking/optimistic.rb:84:in `_create_record'
activerecord-7.1.4/lib/active_record/encryption/encryptable_record.rb:184:in `_create_record'
activerecord-7.1.4/lib/active_record/attribute_methods/dirty.rb:240:in `_create_record'
activerecord-7.1.4/lib/active_record/callbacks.rb:445:in `block in _create_record'
activesupport-7.1.4/lib/active_support/callbacks.rb:110:in `run_callbacks'
activesupport-7.1.4/lib/active_support/callbacks.rb:952:in `_run_create_callbacks'
activerecord-7.1.4/lib/active_record/callbacks.rb:445:in `_create_record'
activerecord-7.1.4/lib/active_record/timestamp.rb:116:in `_create_record'
activerecord-7.1.4/lib/active_record/persistence.rb:1221:in `create_or_update'
activerecord-7.1.4/lib/active_record/callbacks.rb:441:in `block in create_or_update'
activesupport-7.1.4/lib/active_support/callbacks.rb:121:in `block in run_callbacks'
activerecord-7.1.4/lib/active_record/autosave_association.rb:375:in `around_save_collection_association'
activesupport-7.1.4/lib/active_support/callbacks.rb:130:in `block in run_callbacks'
activesupport-7.1.4/lib/active_support/callbacks.rb:141:in `run_callbacks'
activesupport-7.1.4/lib/active_support/callbacks.rb:952:in `_run_save_callbacks'
activerecord-7.1.4/lib/active_record/callbacks.rb:441:in `create_or_update'
activerecord-7.1.4/lib/active_record/timestamp.rb:127:in `create_or_update'
activerecord-7.1.4/lib/active_record/persistence.rb:751:in `save!'
activerecord-7.1.4/lib/active_record/validations.rb:55:in `save!'
activerecord-7.1.4/lib/active_record/transactions.rb:313:in `block in save!'
activerecord-7.1.4/lib/active_record/transactions.rb:365:in `block in with_transaction_returning_status'
activerecord-7.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:342:in `transaction'
activerecord-7.1.4/lib/active_record/transactions.rb:361:in `with_transaction_returning_status'
activerecord-7.1.4/lib/active_record/transactions.rb:313:in `save!'
activerecord-7.1.4/lib/active_record/suppressor.rb:56:in `save!'
/var/www/discourse/plugins/chat/app/services/chat/create_message.rb:159:in `save_message'
/var/www/discourse/app/services/service/base.rb:117:in `instance_exec'
/var/www/discourse/app/services/service/base.rb:117:in `call'
/var/www/discourse/app/services/service/base.rb:207:in `block (2 levels) in call'
/var/www/discourse/app/services/service/base.rb:207:in `each'
/var/www/discourse/app/services/service/base.rb:207:in `block in call'
activerecord-7.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:535:in `block in within_new_transaction'
activesupport-7.1.4/lib/active_support/concurrency/null_lock.rb:9:in `synchronize'
activerecord-7.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:532:in `within_new_transaction'
activerecord-7.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:344:in `transaction'
activerecord-7.1.4/lib/active_record/transactions.rb:212:in `transaction'
/var/www/discourse/app/services/service/base.rb:207:in `call'
/var/www/discourse/app/services/service/base.rb:374:in `block in run!'
/var/www/discourse/app/services/service/base.rb:374:in `each'
/var/www/discourse/app/services/service/base.rb:374:in `run!'
/var/www/discourse/app/services/service/base.rb:367:in `run'
<internal:kernel>:90:in `tap'
/var/www/discourse/app/services/service/base.rb:234:in `call'
/var/www/discourse/lib/service_runner.rb:141:in `block in setup_and_run_service'
/var/www/discourse/lib/service_runner.rb:138:in `instance_eval'
/var/www/discourse/lib/service_runner.rb:138:in `setup_and_run_service'
/var/www/discourse/lib/service_runner.rb:121:in `call'
/var/www/discourse/lib/service_runner.rb:115:in `call'
/var/www/discourse/app/services/service/base.rb:235:in `call'
/var/www/discourse/plugins/chat/app/controllers/chat/api/channel_messages_controller.rb:71:in `create'
actionpack-7.1.4/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
actionpack-7.1.4/lib/abstract_controller/base.rb:224:in `process_action'
actionpack-7.1.4/lib/action_controller/metal/rendering.rb:165:in `process_action'
actionpack-7.1.4/lib/abstract_controller/callbacks.rb:259:in `block in process_action'
activesupport-7.1.4/lib/active_support/callbacks.rb:121:in `block in run_callbacks'
/var/www/discourse/app/controllers/application_controller.rb:424:in `block in with_resolved_locale'
i18n-1.14.5/lib/i18n.rb:351:in `with_locale'
/var/www/discourse/app/controllers/application_controller.rb:424:in `with_resolved_locale'
activesupport-7.1.4/lib/active_support/callbacks.rb:130:in `block in run_callbacks'
activesupport-7.1.4/lib/active_support/callbacks.rb:141:in `run_callbacks'
actionpack-7.1.4/lib/abstract_controller/callbacks.rb:258:in `process_action'
actionpack-7.1.4/lib/action_controller/metal/rescue.rb:25:in `process_action'
actionpack-7.1.4/lib/action_controller/metal/instrumentation.rb:74:in `block in process_action'
activesupport-7.1.4/lib/active_support/notifications.rb:206:in `block in instrument'
activesupport-7.1.4/lib/active_support/notifications/instrumenter.rb:58:in `instrument'
activesupport-7.1.4/lib/active_support/notifications.rb:206:in `instrument'
actionpack-7.1.4/lib/action_controller/metal/instrumentation.rb:73:in `process_action'
actionpack-7.1.4/lib/action_controller/metal/params_wrapper.rb:261:in `process_action'
activerecord-7.1.4/lib/active_record/railties/controller_runtime.rb:32:in `process_action'
actionpack-7.1.4/lib/abstract_controller/base.rb:160:in `process'
actionview-7.1.4/lib/action_view/rendering.rb:40:in `process'
rack-mini-profiler-3.3.1/lib/mini_profiler/profiling_methods.rb:115:in `block in profile_method'
actionpack-7.1.4/lib/action_controller/metal.rb:227:in `dispatch'
actionpack-7.1.4/lib/action_controller/metal.rb:309:in `dispatch'
actionpack-7.1.4/lib/action_dispatch/routing/route_set.rb:49:in `dispatch'
actionpack-7.1.4/lib/action_dispatch/routing/route_set.rb:32:in `serve'
actionpack-7.1.4/lib/action_dispatch/journey/router.rb:51:in `block in serve'
actionpack-7.1.4/lib/action_dispatch/journey/router.rb:131:in `block in find_routes'
actionpack-7.1.4/lib/action_dispatch/journey/router.rb:124:in `each'
actionpack-7.1.4/lib/action_dispatch/journey/router.rb:124:in `find_routes'
actionpack-7.1.4/lib/action_dispatch/journey/router.rb:32:in `serve'
actionpack-7.1.4/lib/action_dispatch/routing/route_set.rb:882:in `call'
railties-7.1.4/lib/rails/engine.rb:536:in `call'
railties-7.1.4/lib/rails/railtie.rb:226:in `public_send'
railties-7.1.4/lib/rails/railtie.rb:226:in `method_missing'
actionpack-7.1.4/lib/action_dispatch/routing/mapper.rb:31:in `block in <class:Constraints>'
actionpack-7.1.4/lib/action_dispatch/routing/mapper.rb:60:in `serve'
actionpack-7.1.4/lib/action_dispatch/journey/router.rb:51:in `block in serve'
actionpack-7.1.4/lib/action_dispatch/journey/router.rb:131:in `block in find_routes'
actionpack-7.1.4/lib/action_dispatch/journey/router.rb:124:in `each'
actionpack-7.1.4/lib/action_dispatch/journey/router.rb:124:in `find_routes'
actionpack-7.1.4/lib/action_dispatch/journey/router.rb:32:in `serve'
actionpack-7.1.4/lib/action_dispatch/routing/route_set.rb:882:in `call'
/var/www/discourse/lib/middleware/omniauth_bypass_middleware.rb:64:in `call'
rack-2.2.9/lib/rack/tempfile_reaper.rb:15:in `call'
rack-2.2.9/lib/rack/conditional_get.rb:40:in `call'
rack-2.2.9/lib/rack/head.rb:12:in `call'
actionpack-7.1.4/lib/action_dispatch/http/permissions_policy.rb:36:in `call'
/var/www/discourse/lib/content_security_policy/middleware.rb:12:in `call'
/var/www/discourse/lib/middleware/anonymous_cache.rb:393:in `call'
/var/www/discourse/lib/middlewar
2개의 좋아요

채팅 테이블에 삽입을 시도하고 있으며 해당 열은 1000자로 제한되어 있습니다.

데이터 탐색기에서 다음을 시도해 보세요:

SELECT 
    column_name, 
    data_type, 
    character_maximum_length
FROM 
    information_schema.columns
WHERE 
    table_name = 'chat_messages'
    AND column_name IN ('cooked', 'message')

스키마에 최대 길이가 어떻게 정의되어 있나요?

2개의 좋아요

value too long for type character varying(1000) 오류는 발췌문(excerpt)과 관련이 있는 것 같습니다. 이는 놀라운 점인데, 기술적으로 발췌문을 150자로 제한하고 있기 때문에 이런 경우는 절대 발생하지 않아야 하기 때문입니다. 처음에는 발췌문 생성기의 버그라고 생각했지만, 채팅에서 발췌문 코드를 살펴보니 다음과 같은 내용을 확인했습니다:

def build_excerpt
  # 메시지 전체가 URL인 경우, 원박스를 발췌할 수 없으므로 URL만 표시합니다
  return message if UrlHelper.relaxed_parse(message).is_a?(URI)

  # 업로드 전용 메시지는 파일명으로 표현하는 것이 더 좋습니다
  return uploads.first.original_filename if cooked.blank? && uploads.present?

 # 인용구와 같은 복잡한 경우를 위해 빈 값을 반환할 수 있으며, 이는 허용됩니다
  PrettyText.excerpt(cooked, EXCERPT_LENGTH, strip_links: true, keep_mentions: true)
end

간단한 디버깅 결과, 실제로 PrettyText.excerpt에는 도달하지 못하고 첫 번째 return에서 중단되는 것을 확인했습니다. Apparently ???가 우리의 코드로 하여금 이것이 URL이라고 생각하게 만드는 것 같습니다:

[1] pry(main)> UrlHelper.relaxed_parse("???\ntest").is_a?(URI)
=> true
3개의 좋아요

수정 사항을 확인했습니다. 다만 main 브랜치에 반영되기까지 시간이 좀 걸릴 것입니다.

2개의 좋아요

수정 사항이 병합되었습니다: SECURITY: Correctly parse URLs in chat excerpts · discourse/discourse@1da97de · GitHub

4개의 좋아요

이 주제는 마지막 답변 후 3일이 지나면 자동으로 닫힙니다. 더 이상 새 답변을 게시할 수 없습니다.