xebialabs-community / xlr-teamcity-plugin

A plugin to orchestrate and visualize TeamCity agents, pools, and builds.
MIT License
2 stars 3 forks source link

set_ca_bundle_path will set os.environ['REQUESTS_CA_BUNDLE'] to None and cause popen to fail with NPE #22

Open ilx opened 2 years ago

ilx commented 2 years ago
def set_ca_bundle_path():
    ca_bundle_path = extract_file_from_jar("requests/cacert.pem")
    os.environ['REQUESTS_CA_BUNDLE'] = ca_bundle_path

def extract_file_from_jar(config_file):
    file_url = LoaderUtil.getResourceBySelfClassLoader(config_file)
    if file_url:
        tmp_file, tmp_abs_path = tempfile.mkstemp()
        tmp_file.close()
        Files.copy(file_url.openStream(), Paths.get(
            tmp_abs_path), StandardCopyOption.REPLACE_EXISTING)
        return tmp_abs_path
    else:
        return None

if file is not present it will populate env with None - this causes NPE in

org.python.core.Py.fileSystemDecode(Py.java:699)

and

        at subprocess$py._setup_env$21(subprocess.py:827)
        at subprocess$py.call_function(subprocess.py)

this is the code in subprocess.py:

if jython:
    def _setup_env(env, builder_env):
        """Carefully merge env with ProcessBuilder's only
        overwriting key/values that differ

        System.getenv (Map<String, String>) may be backed by
        <byte[], byte[]> on UNIX platforms where these are really
        bytes. ProcessBuilder's env inherits its contents and will
        maintain those byte values (which may be butchered as
        Strings) for the subprocess if they haven't been modified.
        """
        # Determine what's necessary to merge (new or different)
        merge_env = dict((key, value) for key, value in env.iteritems()
                         if key not in builder_env or
                         builder_env.get(key) != value)

        # Prune anything not in env
        entries = builder_env.entrySet().iterator()
        for entry in entries:
            if entry.getKey() not in env:
                entries.remove()
        # add anything new or different in env
        for key, value in merge_env.iteritems():
            # If the new value is bytes, assume it to be FS-encoded
            builder_env.put(key, fileSystemDecode(value))

if value is None fileSystemDecode explodes:

    public static String fileSystemDecode(PyString filename) {
        String s = filename.getString();
        if (filename instanceof PyUnicode || CharMatcher.ascii().matchesAllOf(s)) {
            // Already encoded or usable as ASCII
            return s;
        } else {
            // It's bytes, so must decode properly
            assert "utf-8".equals(PySystemState.FILE_SYSTEM_ENCODING.toString());
            return codecs.PyUnicode_DecodeUTF8(s, null);
        }
    }

Since os.environ is global and shared with all modules this should be prevented.