Skip to content

rcache contains invalid data after read error, causing incorrect data returned by lfs_read() #1205

@simaodangan

Description

@simaodangan

Description

After a file is successfully opened and written, if the SD card fails (for example, the card is removed), subsequent operations may behave incorrectly.

A simplified example:

file = lfs_open();                     // ok
lfs_write(file, "something 1");        // ok

// now remove sd card, so lfs->cfg->read() returns a negative error code
lfs_write(file, "something 2");        // failed

error_code = lfs_read(file, buffer);   // return code is "OK", but data is invalid

In this scenario:

  • lfs_write("something 2") correctly returns an error
  • However, lfs_read() returns success, but the returned data is invalid

This appears to be caused by rcache containing stale/invalid data.

Root Cause Analysis

lfs_write(file, "something 2") calls:

lfs_file_flushedwrite()
  → lfs_ctz_find()
      → lfs_bd_read()

Inside lfs_bd_read():

rcache->block = block;
rcache->off = lfs_aligndown(off, lfs->cfg->read_size);
rcache->size = lfs_min(
        lfs_min(
            lfs_alignup(off+hint, lfs->cfg->read_size),
            lfs->cfg->block_size)
        - rcache->off,
        lfs->cfg->cache_size);

int err = lfs->cfg->read(lfs->cfg, rcache->block,
        rcache->off, rcache->buffer, rcache->size);

LFS_ASSERT(err <= 0);

if (err) {
    return err;
}

If lfs->cfg->read() returns an error:

  • rcache->block, rcache->off, and rcache->size are already updated
  • rcache->buffer still contains invalid / partial data
  • The cache is not cleared

Later, lfs_read() may use this invalid rcache data and return incorrect content.

Proposed Fix

Would the following change be appropriate?

if (err) {
    lfs_cache_drop(lfs, rcache);
    return err;
}

This ensures that invalid cache data is not reused after a failed read.

Question

Is this the correct fix, or is there a reason why rcache should remain unchanged on read failure?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions