Skip to content

Python: Inconsistent behaviour of the getAMember predicate #19297

Open
@tanguySnoeck

Description

@tanguySnoeck

Trying to access all nodes that represent an attribute of a Django subclass does not work as expected in https://github.com/HumanSignal/label-studio.

I am trying to detect a call to AsyncMigrationStatus.objects in the following block of code (https://github.com/HumanSignal/label-studio/blob/develop/label_studio/core/management/commands/show_async_migrations.py#L19):

def handle(self, *args, **options):
        org = options['organization']
        logger.debug(f"===> AsyncMigrationStatus for Organization {org if org > -1 else 'ALL'}")
        if org == -1:
            migrations = AsyncMigrationStatus.objects.all().order_by('project_id')
        else:
            migrations = AsyncMigrationStatus.objects.filter(project__organization_id=org)

        for m in migrations:
            logger.debug(f'{m.name} \t {m.created_at} \t Project <{m.project}> \t {m.status} \t {m.meta}')

        logger.debug(f"===> AsyncMigrationStatus for Organization {org if org > -1 else 'ALL'} printed")

Using the following query:

import python
import semmle.python.frameworks.Django
import semmle.python.ApiGraphs


from API::Node n 
where
n = PrivateDjango::DjangoImpl::DB::Models::Model::subclassRef().getAMember() and
select n, "this is a model attribute"

AsyncMigrationStatus is defined below (https://github.com/HumanSignal/label-studio/blob/develop/label_studio/core/models.py#L10):

class AsyncMigrationStatus(models.Model):
    meta = JSONField(
        'meta',
        null=True,
        default=dict,
        help_text='Meta is for any params for migrations, e.g.: project, filter or error message.',
    )

    project = models.ForeignKey(
        'projects.Project',
        related_name='asyncmigrationstatus',
        on_delete=models.CASCADE,
        null=True,
        help_text='Project ID for this migration',
    )

    name = models.TextField('migration_name', help_text='Migration name')

    STATUS_STARTED = 'STARTED'
    STATUS_IN_PROGRESS = 'IN PROGRESS'
    STATUS_FINISHED = 'FINISHED'
    STATUS_ERROR = 'ERROR'
    STATUS_CHOICES = (
        (STATUS_STARTED, 'Migration is started or queued.'),
        (STATUS_IN_PROGRESS, 'Migration is in progress. Check meta for job_id or status.'),
        (STATUS_FINISHED, 'Migration completed successfully.'),
        (STATUS_ERROR, 'Migration completed with errors. Check meta for more info.'),
    )
    status = models.CharField(max_length=100, choices=STATUS_CHOICES, null=True, default=None)

    created_at = models.DateTimeField(_('created at'), auto_now_add=True, help_text='Creation time')
    updated_at = models.DateTimeField(_('updated at'), auto_now=True, help_text='Last updated time')

    def __str__(self):
        return f'(id={self.id}) ' + self.name + (' at project ' + str(self.project) if self.project else ''))

This query returns many results across the codebase but does not flag this specific statement, along with others.

I've tried many different approaches to understand the root cause of the issue without success. Please let me know if I am somehow misusing getAMember.

Below are my specs:

  • codeQL CLI 2.21.0
  • codeQL VSCode extension 1.17.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions