Skip to content

Connecting via unix socket on a specific DB crashes pgcli #1422

Open

Description

@P-EB

Description

Hello

Installing pgcli 3.5.0 on a Debian server with postgresql 15, when, as unix user postgres, I run a simple pgcli, I get a proper prompt, but as soon as I use pgcli XXX with XXXbeing another database, pgcli crashes while starting because it tries to mix str and bytes.

postgres@pgsql:~$ pgcli                                                             
Server: PostgreSQL 15.3 (Debian 15.3-0+deb12u1)
Version: 3.5.0            
Home: http://pgcli.com                                                                                                                                                     
postgres>                                                                                                                                                                                                                                                                                                                                             
Goodbye!                      
postgres@pgsql:~$ pgcli icinga2                                                                                                                                            
Server: PostgreSQL 15.3 (Debian 15.3-0+deb12u1)
Version: 3.5.0                                                                                                                                                             
Home: http://pgcli.com                     
Traceback (most recent call last):                                                                                                                                         
  File "/usr/bin/pgcli", line 33, in <module>
Exception in thread completion_refresh:                                                                                                                                    
Traceback (most recent call last):                                       
  File "/usr/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
    sys.exit(load_entry_point('pgcli==3.5.0', 'console_scripts', 'pgcli')())                                                                                               
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/click/core.py", line 1130, in __call__
    self.run()                                                                                                                                                             
  File "/usr/lib/python3.11/threading.py", line 975, in run                    
    return self.main(*args, **kwargs)              
           ^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                      
  File "/usr/lib/python3/dist-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)                                            
         ^^^^^^^^^^^^^^^^                                                                                                                                                  
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3/dist-packages/pgcli/completion_refresher.py", line 68, in _bg_refresh
  File "/usr/lib/python3/dist-packages/click/core.py", line 1404, in invoke                                                                                                
    refresher(completer, executor)                                             
  File "/usr/lib/python3/dist-packages/pgcli/completion_refresher.py", line 109, in refresh_schemata
    return ctx.invoke(self.callback, **ctx.params)                                                                                                                         
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/click/core.py", line 760, in invoke
    completer.set_search_path(executor.search_path())                                                                                                                      
  File "/usr/lib/python3/dist-packages/pgcli/pgcompleter.py", line 306, in set_search_path
    return __callback(*args, **kwargs)
    self.search_path = self.escaped_names(search_path)                                                                                                                     
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^          
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/pgcli/main.py", line 1427, in cli                                                                                                   
  File "/usr/lib/python3/dist-packages/pgcli/pgcompleter.py", line 150, in escaped_names
    return [self.escape_name(name) for name in names]           
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                      
  File "/usr/lib/python3/dist-packages/pgcli/pgcompleter.py", line 150, in <listcomp> 
    pgcli.run_cli()                 
  File "/usr/lib/python3/dist-packages/pgcli/main.py", line 788, in run_cli    
    return [self.escape_name(name) for name in names]
            ^^^^^^^^^^^^^^^^^^^^^^         
  File "/usr/lib/python3/dist-packages/pgcli/pgcompleter.py", line 131, in escape_name
    text = self.prompt_app.prompt()                                
           ^^^^^^^^^^^^^^^^^^^^^^^^                                
  File "/usr/lib/python3/dist-packages/prompt_toolkit/shortcuts/prompt.py", line 1034, in prompt
    (not self.name_pattern.match(name))

TypeError: cannot use a string pattern on a bytes-like object
    return self.app.run(          
           ^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/application/application.py", line 978, in run
    return loop.run_until_complete(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
    return future.result()                                           
           ^^^^^^^^^^^^^^^      
  File "/usr/lib/python3/dist-packages/prompt_toolkit/application/application.py", line 885, in run_async
    return await _run_async(f)
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/application/application.py", line 743, in _run_async
    self._redraw()
  File "/usr/lib/python3/dist-packages/prompt_toolkit/application/application.py", line 557, in _redraw
    self.context.copy().run(run_in_context)
  File "/usr/lib/python3/dist-packages/prompt_toolkit/application/application.py", line 540, in run_in_context
    self.renderer.render(self, self.layout)
  File "/usr/lib/python3/dist-packages/prompt_toolkit/renderer.py", line 640, in render
    layout.container.preferred_height(size.columns, size.rows).preferred,
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 326, in preferred_height
    dimensions = [
                 ^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 327, in <listcomp>
    c.preferred_height(width, max_available_height) for c in self._all_children
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 796, in preferred_height
    return self.content.preferred_height(width, max_available_height)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 326, in preferred_height
    dimensions = [
                 ^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 327, in <listcomp>
    c.preferred_height(width, max_available_height) for c in self._all_children
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 2642, in preferred_height
    if self.filter():
       ^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/filters/base.py", line 210, in __call__
    return self.func()
           ^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/shortcuts/prompt.py", line 168, in has_before_fragments
    for fragment, char, *_ in get_prompt_text():
                              ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/shortcuts/prompt.py", line 1279, in _get_prompt
    return to_formatted_text(self.message, style="class:prompt")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/prompt_toolkit/formatted_text/base.py", line 81, in to_formatted_text
    return to_formatted_text(value(), style=style)
                             ^^^^^^^
  File "/usr/lib/python3/dist-packages/pgcli/main.py", line 851, in get_message
    prompt = self.get_prompt(prompt_format)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/pgcli/main.py", line 1115, in get_prompt
    string = string.replace("\\H", self.pgexecute.host or "(none)")
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: replace() argument 2 must be str, not bytes
postgres@pgsql:~$ ;1R

As you see, there are two type errors, and both relate to mixing str and bytes.

After poking a bit, it seems that when I give another database as an argument, pgcli connects to it and then makes queries to the postgres database to get the unix socket configuration and other stufs from the pg_settings database. In the case of a connection to the postgres database, the cursor fetches strings (eg in pgexecute.get_socket_directory function), while when connected to another database, the cursor fetches bytes.

I think some sanitizing is needed.

Your environment

  • Please provide your OS and version information. Debian 12
  • Please provide your CLI version. 3.5.0
  • What is the output of pip freeze command: nothing, I don't use pip. psycopg version is 3.1.7

Activity

  1. j-bennet commented on Oct 7, 2023

    @j-bennet
    Contributor

    @P-EB Thank you for reporting. What's the python version, and how did you install pgcli (you said it was not pip)?

  2. P-EB commented on Oct 9, 2023

    @P-EB
    Author

    Via apt, as I'm using Debian.

    Python3 version is 3.11.5

  3. P-EB commented on Oct 13, 2023

    @P-EB
    Author

    @j-bennet in case you did not see it I replied to your question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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