python.lang.correctness.tempfile.flush.tempfile-without-flush

Verifed by r2c
Community Favorite
profile photo of semgrepsemgrep
Author
111,531
Download Count*

Using '$F.name' without '.flush()' or '.close()' may cause an error because the file may not exist when '$F.name' is used. Use '.flush()' or close the file before using '$F.name'.

Run Locally

Run in CI

Defintion

rules:
  - id: tempfile-without-flush
    languages:
      - python
    message: Using '$F.name' without '.flush()' or '.close()' may cause an error
      because the file may not exist when '$F.name' is used. Use '.flush()' or
      close the file before using '$F.name'.
    pattern-either:
      - patterns:
          - pattern-not-inside: |
              $F = tempfile.NamedTemporaryFile(...)
              ...
              $F.write(...)
              ...
              $F.flush()
              ...
              $F.name
          - pattern-not-inside: |
              $F = tempfile.NamedTemporaryFile(...)
              ...
              $F.write(...)
              ...
              $F.close()
              ...
              $F.name
          - pattern-not-inside: |
              $F = tempfile.NamedTemporaryFile(..., delete=False, ...)
              ...
              $F.close()
              ...
              $F.name
          - pattern-inside: |
              $F = tempfile.NamedTemporaryFile(...)
              ...
          - pattern: |
              $F.name
      - patterns:
          - pattern-not-inside: |
              with tempfile.NamedTemporaryFile(...) as $F:
                  ...
                  $F.write(...)
                  ...
                  $F.flush()
                  ...
                  $F.name
          - pattern-not-inside: |
              with tempfile.NamedTemporaryFile(...) as $F:
                  ...
                  $F.write(...)
                  ...
                  $F.close()
                  ...
                  $F.name
          - pattern-not-inside: |
              with tempfile.NamedTemporaryFile(...) as $F:
                  ...
                  $MODULE.dump(..., $F, ...)
                  ...
                  $F.flush()
                  ...
                  $F.name
          - pattern-not-inside: |
              with tempfile.NamedTemporaryFile(...) as $F:
                  ...
                  $MODULE.dump(..., $F, ...)
                  ...
                  $F.close()
                  ...
                  $F.name
          - pattern-inside: |
              with tempfile.NamedTemporaryFile(...) as $F:
                  ...
          - pattern: |
              $F.name
    severity: ERROR
    metadata:
      category: correctness
      technology:
        - python
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]

Examples

flush.py

import tempfile

import at
import tf


def main():
    with tempfile.NamedTemporaryFile("w") as fout:
        debug_print(astr)
        fout.write(astr)
        # ok:tempfile-without-flush
        fout.flush()
        cmd = [binary_name, fout.name, *[str(path) for path in targets]]


def main_b():
    with tempfile.NamedTemporaryFile("w") as fout:
        debug_print(astr)
        fout.write(astr)
        # ok:tempfile-without-flush
        fout.close()
        cmd = [binary_name, fout.name, *[str(path) for path in targets]]


def main_c():
    with tempfile.NamedTemporaryFile("w") as fout:
        debug_print(astr)
        fout.write(astr)

    # ok:tempfile-without-flush
    cmd = [binary_name, fout.name, *[str(path) for path in targets]]


def main_c():
    with tempfile.NamedTemporaryFile("w") as fout:
        debug_print(astr)
        fout.write(astr)
        debug_print('wrote file')

        # ruleid:tempfile-without-flush
        cmd = [binary_name, fout.name, *[str(path) for path in targets]]


def main_d():
    fout = tempfile.NamedTemporaryFile('w')
    debug_print(astr)
    fout.write(astr)

    # ruleid:tempfile-without-flush
    fout.name
    # ruleid:tempfile-without-flush
    cmd = [binary_name, fout.name, *[str(path) for path in targets]]


def main_e():
    fout = tempfile.NamedTemporaryFile('w')
    debug_print(astr)
    fout.write(astr)

    # ruleid:tempfile-without-flush
    print(fout.name)
    # ruleid:tempfile-without-flush
    cmd = [binary_name, fout.name, *[str(path) for path in targets]]


def main_f():
    fout = tempfile.NamedTemporaryFile('w', delete=False)
    debug_print(astr)
    fout.close()

    # ok:tempfile-without-flush
    print(fout.name)

def main_g(language, rule, target_manager, rule):
    with tempfile.NamedTemporaryFile(
        "w", suffix=".yaml"
    ) as rule_file, tempfile.NamedTemporaryFile("w") as target_file:
        targets = self.get_files_for_language(language, rule, target_manager)
        target_file.write("\n".join(map(lambda p: str(p), targets)))
        target_file.flush()
        yaml = YAML()
        yaml.dump({"rules": [rule._raw]}, rule_file)
        rule_file.flush()

        cmd = [SEMGREP_PATH] + [
            "-lang",
            language,
            "-fast",
            "-json",
            "-config",
            # ok: tempfile-without-flush
            rule_file.name
        ]