fix: validate community events read from database

Despite the expectation that only validated events are stored in the
database, instances have been identified where invalid events are saved.
This can lead to unexpected behavior or crashes.

This commit adds validation for community events read from the database
to prevent such cases.

**NOTE**: this fix does not address the root cause, which involves
invalid events being saved to the database. The exact scenario leading
to this issue has yet to be identified.

mitigates: status-im/status-desktop#14106
This commit is contained in:
Patryk Osmaczko 2024-03-25 20:02:38 +01:00 committed by osmaczko
parent 48af7a6f49
commit 5b7910ae5a
1 changed files with 28 additions and 23 deletions

View File

@ -71,32 +71,26 @@ func (e *eventsProcessor) validateDescription() error {
return nil
}
// Filter invalid and outdated events.
func (e *eventsProcessor) filterEvents() {
validateEvent := func(event *CommunityEvent) error {
if e.lastlyAppliedEvents != nil {
if clock, found := e.lastlyAppliedEvents[event.EventTypeID()]; found && clock >= event.CommunityEventClock {
return errors.New("event outdated")
}
func (e *eventsProcessor) validateEvent(event *CommunityEvent) error {
if e.lastlyAppliedEvents != nil {
if clock, found := e.lastlyAppliedEvents[event.EventTypeID()]; found && clock >= event.CommunityEventClock {
return errors.New("event outdated")
}
signer, err := event.RecoverSigner()
if err != nil {
return err
}
err = e.community.validateEvent(event, signer)
if err != nil {
return err
}
return nil
}
for i := range e.message.Events {
event := e.message.Events[i]
signer, err := event.RecoverSigner()
if err != nil {
return err
}
if err := validateEvent(&event); err == nil {
return e.community.validateEvent(event, signer)
}
// Filter invalid and outdated events.
func (e *eventsProcessor) filterEvents() {
for _, ev := range e.message.Events {
event := ev
if err := e.validateEvent(&event); err == nil {
e.eventsToApply = append(e.eventsToApply, event)
} else {
e.logger.Warn("invalid community event", zap.String("EventTypeID", event.EventTypeID()), zap.Uint64("clock", event.CommunityEventClock), zap.Error(err))
@ -107,7 +101,18 @@ func (e *eventsProcessor) filterEvents() {
// Merge message's events with community's events.
func (e *eventsProcessor) mergeEvents() {
if e.community.config.EventsData != nil {
e.eventsToApply = append(e.eventsToApply, e.community.config.EventsData.Events...)
for _, ev := range e.community.config.EventsData.Events {
event := ev
if err := e.validateEvent(&event); err == nil {
e.eventsToApply = append(e.eventsToApply, event)
} else {
// NOTE: this should not happen, events should be validated before they are saved in the db.
// It has been identified that an invalid event is saved to the database for some reason.
// The code flow leading to this behavior is not yet known.
// https://github.com/status-im/status-desktop/issues/14106
e.logger.Error("invalid community event read from db", zap.String("EventTypeID", event.EventTypeID()), zap.Uint64("clock", event.CommunityEventClock), zap.Error(err))
}
}
}
}