Skip to content

Commit

Permalink
refs #3504 injection fixes (#3505)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidnich committed Aug 20, 2019
1 parent e63cf6c commit 550bf41
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 145 deletions.
4 changes: 4 additions & 0 deletions doxygen/lang/900_release_notes.dox.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
- added the @ref Qore::UrlInfo hash as the return type to:
- @ref Qore::parse_url() "parse_url()"
- @ref Qore::parseURL() "parseURL()"
- added the \a module_visibility parameter to @ref Qore::Program::importClass() "Program::importClass()" and the
@ref import_visibility_constants as possible argument values
- the <a href="../../modules/RestClient/html/index.html">RestClient</a> module was updated so that
\c RestConnection objects now support the \c "headers" option
(<a href="https://github.com/qorelanguage/qore/issues/3455">issue 3455</a>)
Expand All @@ -53,6 +55,8 @@
(<a href="https://github.com/qorelanguage/qore/issues/3392">issue 3392</a>)

@subsection qore_093_bug_fixes Bug Fixes in Qore
- fixed bugs importing user modules with an injected API in an existing @ref Qore::Program "Program" container
(<a href="https://github.com/qorelanguage/qore/issues/3504">issue 3504</a>)
- fixed a memory leak in @ref Qore::Serializable::deserialize(string) "Serializable::deserialize(string)"
- fixed a bug where HTTP redirect messages with a simple path and not a full URL were not processed correctly
(<a href="https://github.com/qorelanguage/qore/issues/3475">issue 3475</a>)
Expand Down
11 changes: 11 additions & 0 deletions examples/test/qore/misc/module-loader/Issue3504.qm
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Issue3504 {
version = "1.0";
desc = "issue #3504 test module";
author = "Qore Technologies, s.r.o.";
url = "https://qore.org";
license = "MIT";
}

public namespace Util {
public sub t() {}
}
32 changes: 32 additions & 0 deletions examples/test/qore/misc/module-loader/issue-3504.qtest
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env qore
# -*- mode: qore; indent-tabs-mode: nil -*-

%new-style
%enable-all-warnings
%require-types
%strict-args
%allow-injection

%requires ../../../../../qlib/Util.qm
%requires ../../../../../qlib/QUnit.qm

%requires ./Issue3504.qm

%exec-class Issue3504Test

class Issue3504Test inherits QUnit::Test {
constructor() : Test("Issue3504Test", "1.0") {
addTestCase("Issue3504Test Test", \test());

set_return_value(main());
}

test() {
Program p0(PO_NO_USER_API);
p0.importFunction("t");
p0.loadApplyToUserModule("Util", True);
Program p1();
p1.loadModule("Util");
assertEq(Type::String, p1.callFunction("get_random_string").type());
}
}
46 changes: 24 additions & 22 deletions include/qore/intern/FunctionList.h
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
/* -*- mode: c++; indent-tabs-mode: nil -*- */
/*
FunctionList.h
FunctionList.h
Qore Programming Language
Qore Programming Language
Copyright (C) 2003 - 2018 Qore Technologies, s.r.o.
Copyright (C) 2003 - 2019 Qore Technologies, s.r.o.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Note that the Qore library is released under a choice of three open-source
licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
information.
Note that the Qore library is released under a choice of three open-source
licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
information.
*/

#ifndef _QORE_FUNCTIONLIST_H
Expand Down Expand Up @@ -168,8 +168,10 @@ class FunctionList : public fl_map_t {

DLLLOCAL void mergeUserPublic(const FunctionList& src, qore_ns_private* ns) {
for (fl_map_t::const_iterator i = src.begin(), e = src.end(); i != e; ++i) {
if (!i->second->isUserPublic())
if (!i->second->isUserPublic()) {
//printd(5, "FunctionList::mergePublic() this: %p SKIPPING %s!\n", this, i->first);
continue;
}

assert(!findNode(i->first));
FunctionEntry* fe = new ModuleImportedFunctionEntry(*i->second, ns);
Expand Down
6 changes: 3 additions & 3 deletions include/qore/intern/QoreClassIntern.h
Original file line number Diff line number Diff line change
Expand Up @@ -1818,7 +1818,7 @@ class qore_class_private {

// only called while the parse lock for the QoreProgram owning "old" is held
// called for injected classes only
DLLLOCAL qore_class_private(const qore_class_private& old, qore_ns_private* ns, QoreProgram* spgm, const char* nme, bool inject, const qore_class_private* injectedClass);
DLLLOCAL qore_class_private(const qore_class_private& old, qore_ns_private* ns, QoreProgram* spgm, const char* nme, bool inject, const qore_class_private* injectedClass, q_setpub_t set_pub);

public:
DLLLOCAL const char* getModuleName() const {
Expand Down Expand Up @@ -3033,8 +3033,8 @@ class qore_class_private {
return qc.priv->inject;
}

DLLLOCAL static QoreClass* makeImportClass(const QoreClass& qc, QoreProgram* spgm, const char* nme, bool inject, const qore_class_private* injectedClass, qore_ns_private* ns) {
qore_class_private* priv = new qore_class_private(*qc.priv, ns, spgm, nme, inject, injectedClass);
DLLLOCAL static QoreClass* makeImportClass(const QoreClass& qc, QoreProgram* spgm, const char* nme, bool inject, const qore_class_private* injectedClass, qore_ns_private* ns, q_setpub_t set_pub) {
qore_class_private* priv = new qore_class_private(*qc.priv, ns, spgm, nme, inject, injectedClass, set_pub);
//printd(5, "qore_program_private::makeImportClass() name: '%s' as '%s' inject: %d rv: %p\n", qc.getName(), priv->name.c_str(), inject, priv->cls);
return priv->cls;
}
Expand Down
7 changes: 7 additions & 0 deletions include/qore/intern/QoreLibIntern.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ extern char* strcasestr(const char* s1, const char* s2);

typedef std::set<QoreObject*> obj_set_t;

//! for object import APIs to set the new public / private flag
enum q_setpub_t : unsigned char {
CSP_UNCHANGED = 0,
CSP_SETPRIV = 1,
CSP_SETPUB = 2,
};

DLLLOCAL void parse_init_value(QoreValue& val, LocalVar* oflag, int pflag, int& lvids, const QoreTypeInfo*& typeInfo);

// returns true if the node needs to be scanned for recursive references or not
Expand Down
60 changes: 34 additions & 26 deletions include/qore/intern/QoreNamespaceIntern.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ class qore_ns_private {
return 0;
}

DLLLOCAL FunctionEntry* runtimeImportFunction(ExceptionSink* xsink, QoreFunction* u, const char* new_name = 0, bool inject = false) {
DLLLOCAL FunctionEntry* runtimeImportFunction(ExceptionSink* xsink, QoreFunction* u, const char* new_name = nullptr, bool inject = false) {
const char* fn = new_name ? new_name : u->getName();
if (checkImportFunction(fn, xsink))
return 0;
Expand Down Expand Up @@ -260,15 +260,24 @@ class qore_ns_private {
return 0;
}

DLLLOCAL QoreClass* runtimeImportClass(ExceptionSink* xsink, const QoreClass* c, QoreProgram* spgm, const char* new_name = nullptr, bool inject = false, const qore_class_private* injectedClass = nullptr);
DLLLOCAL QoreClass* runtimeImportClass(ExceptionSink* xsink, const QoreClass* c, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr, bool inject = false, const qore_class_private* injectedClass = nullptr);

DLLLOCAL TypedHashDecl* runtimeImportHashDecl(ExceptionSink* xsink, const TypedHashDecl* hd, QoreProgram* spgm, const char* new_name = nullptr) {
DLLLOCAL TypedHashDecl* runtimeImportHashDecl(ExceptionSink* xsink, const TypedHashDecl* hd, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr) {
if (checkImportHashDecl(new_name ? new_name : hd->getName(), xsink))
return nullptr;

TypedHashDecl* nhd = new TypedHashDecl(*hd);
if (new_name)
typed_hash_decl_private::get(*nhd)->setName(new_name);
if (set_pub == CSP_SETPUB) {
if (!typed_hash_decl_private::get(*nhd)->isPublic()) {
typed_hash_decl_private::get(*nhd)->setPublic();
}
} else if (set_pub == CSP_SETPRIV) {
if (typed_hash_decl_private::get(*nhd)->isPublic()) {
typed_hash_decl_private::get(*nhd)->setPrivate();
}
}
hashDeclList.add(nhd);

return nhd;
Expand All @@ -286,9 +295,9 @@ class qore_ns_private {
return func_list.find(name, false);
}

DLLLOCAL QoreNamespace* findCreateNamespace(const char* nme, bool& is_new, qore_root_ns_private* rns);
DLLLOCAL QoreNamespace* findCreateNamespacePath(const nslist_t& nsl, bool& is_new);
DLLLOCAL QoreNamespace* findCreateNamespacePath(const NamedScope& nspath, bool pub, bool& is_new);
DLLLOCAL QoreNamespace* findCreateNamespace(const char* nme, bool user, bool& is_new, qore_root_ns_private* rns);
DLLLOCAL QoreNamespace* findCreateNamespacePath(const nslist_t& nsl, bool user, bool& is_new);
DLLLOCAL QoreNamespace* findCreateNamespacePath(const NamedScope& nspath, bool pub, bool user, bool& is_new);

DLLLOCAL TypedHashDecl* parseFindLocalHashDecl(const char* name) {
return hashDeclList.find(name);
Expand Down Expand Up @@ -948,8 +957,8 @@ class qore_root_ns_private : public qore_ns_private {
}

// performed at runtime
DLLLOCAL int runtimeImportClass(ExceptionSink* xsink, qore_ns_private& ns, const QoreClass* c, QoreProgram* spgm, const char* new_name = nullptr, bool inject = false, const qore_class_private* injectedClass = nullptr) {
QoreClass* nc = ns.runtimeImportClass(xsink, c, spgm, new_name, inject, injectedClass);
DLLLOCAL int runtimeImportClass(ExceptionSink* xsink, qore_ns_private& ns, const QoreClass* c, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr, bool inject = false, const qore_class_private* injectedClass = nullptr) {
QoreClass* nc = ns.runtimeImportClass(xsink, c, spgm, set_pub, new_name, inject, injectedClass);
if (!nc)
return -1;

Expand All @@ -960,8 +969,8 @@ class qore_root_ns_private : public qore_ns_private {
}

// performed at runtime
DLLLOCAL int runtimeImportHashDecl(ExceptionSink* xsink, qore_ns_private& ns, const TypedHashDecl* hd, QoreProgram* spgm, const char* new_name = nullptr) {
TypedHashDecl* nhd = ns.runtimeImportHashDecl(xsink, hd, spgm, new_name);
DLLLOCAL int runtimeImportHashDecl(ExceptionSink* xsink, qore_ns_private& ns, const TypedHashDecl* hd, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr) {
TypedHashDecl* nhd = ns.runtimeImportHashDecl(xsink, hd, spgm, set_pub, new_name);
if (!nhd)
return -1;

Expand All @@ -972,7 +981,7 @@ class qore_root_ns_private : public qore_ns_private {
}

// performed at runtime
DLLLOCAL int runtimeImportFunction(ExceptionSink* xsink, qore_ns_private& ns, QoreFunction* u, const char* new_name = 0, bool inject = false) {
DLLLOCAL int runtimeImportFunction(ExceptionSink* xsink, qore_ns_private& ns, QoreFunction* u, const char* new_name = nullptr, bool inject = false) {
FunctionEntry* fe = ns.runtimeImportFunction(xsink, u, new_name, inject);
if (!fe)
return -1;
Expand Down Expand Up @@ -1502,8 +1511,7 @@ class qore_root_ns_private : public qore_ns_private {
qoreNS = new QoreNamespace("Qore");
nsl.nsmap.insert(nsmap_t::value_type("Qore", qoreNS));
qoreNS->priv->nsl.nsmap.insert(nsmap_t::value_type("Option", new QoreNamespace("Option")));
}
else
} else
qoreNS = nsl.find("Qore");
assert(qoreNS);

Expand Down Expand Up @@ -1619,24 +1627,24 @@ class qore_root_ns_private : public qore_ns_private {

DLLLOCAL const TypedHashDecl* runtimeFindHashDeclIntern(const NamedScope& name, const qore_ns_private*& ns);

DLLLOCAL QoreNamespace* runtimeFindCreateNamespacePath(const NamedScope& nspath, bool pub) {
DLLLOCAL QoreNamespace* runtimeFindCreateNamespacePath(const NamedScope& nspath, bool pub, bool user) {
assert(nspath.size());
bool is_new = false;
QoreNamespace* nns = findCreateNamespacePath(nspath, pub, is_new);
QoreNamespace* nns = findCreateNamespacePath(nspath, pub, user, is_new);
if (is_new) // add namespace index
nsmap.update(nns->priv);
return nns;
}

DLLLOCAL QoreNamespace* runtimeFindCreateNamespacePath(const qore_ns_private& ns) {
DLLLOCAL QoreNamespace* runtimeFindCreateNamespacePath(const qore_ns_private& ns, bool user) {
// get a list of namespaces from after the root (not including the root) to the current
nslist_t nsl;
ns.getNsList(nsl);

printd(5, "qore_root_ns_private::runtimeFindCreateNamespacePath() this: %p ns: '%s'\n", this, ns.name.c_str());

bool is_new = false;
QoreNamespace* nns = findCreateNamespacePath(nsl, is_new);
QoreNamespace* nns = findCreateNamespacePath(nsl, user, is_new);
assert(ns.name == nns->getName());
if (is_new) // add namespace index
nsmap.update(nns->priv);
Expand Down Expand Up @@ -1697,12 +1705,12 @@ class qore_root_ns_private : public qore_ns_private {
rns.priv->runtimeImportSystemFunctions(*source.priv, *rns.rpriv, xsink);
}

DLLLOCAL static QoreNamespace* runtimeFindCreateNamespacePath(const RootQoreNamespace& rns, const qore_ns_private& ns) {
return rns.rpriv->runtimeFindCreateNamespacePath(ns);
DLLLOCAL static QoreNamespace* runtimeFindCreateNamespacePath(const RootQoreNamespace& rns, const qore_ns_private& ns, bool user) {
return rns.rpriv->runtimeFindCreateNamespacePath(ns, user);
}

DLLLOCAL static QoreNamespace* runtimeFindCreateNamespacePath(const RootQoreNamespace& rns, const NamedScope& nspath, bool pub) {
return rns.rpriv->runtimeFindCreateNamespacePath(nspath, pub);
DLLLOCAL static QoreNamespace* runtimeFindCreateNamespacePath(const RootQoreNamespace& rns, const NamedScope& nspath, bool pub, bool user) {
return rns.rpriv->runtimeFindCreateNamespacePath(nspath, pub, user);
}

DLLLOCAL static RootQoreNamespace* copy(const RootQoreNamespace& rns, int64 po) {
Expand All @@ -1717,16 +1725,16 @@ class qore_root_ns_private : public qore_ns_private {
return getRootNS()->rpriv->addPendingVariantIntern(nsp, name, v);
}

DLLLOCAL static int runtimeImportFunction(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns, QoreFunction* u, const char* new_name = 0, bool inject = false) {
DLLLOCAL static int runtimeImportFunction(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns, QoreFunction* u, const char* new_name = nullptr, bool inject = false) {
return rns.rpriv->runtimeImportFunction(xsink, *ns.priv, u, new_name, inject);
}

DLLLOCAL static int runtimeImportClass(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns, const QoreClass* c, QoreProgram* spgm, const char* new_name = 0, bool inject = false, const qore_class_private* injectedClass = nullptr) {
return rns.rpriv->runtimeImportClass(xsink, *ns.priv, c, spgm, new_name, inject, injectedClass);
DLLLOCAL static int runtimeImportClass(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns, const QoreClass* c, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = 0, bool inject = false, const qore_class_private* injectedClass = nullptr) {
return rns.rpriv->runtimeImportClass(xsink, *ns.priv, c, spgm, set_pub, new_name, inject, injectedClass);
}

DLLLOCAL static int runtimeImportHashDecl(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns, const TypedHashDecl* c, QoreProgram* spgm, const char* new_name = nullptr) {
return rns.rpriv->runtimeImportHashDecl(xsink, *ns.priv, c, spgm, new_name);
DLLLOCAL static int runtimeImportHashDecl(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns, const TypedHashDecl* c, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr) {
return rns.rpriv->runtimeImportHashDecl(xsink, *ns.priv, c, spgm, set_pub, new_name);
}

DLLLOCAL static const QoreClass* runtimeFindClass(RootQoreNamespace& rns, const char* name, const qore_ns_private*& ns) {
Expand Down
4 changes: 2 additions & 2 deletions include/qore/intern/qore_program_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -1695,9 +1695,9 @@ class qore_program_private : public qore_program_private_base {
parse_error(*s->loc, "illegal top-level statement (conflicts with parse option NO_TOP_LEVEL_STATEMENTS)");
}

DLLLOCAL void importClass(ExceptionSink* xsink, qore_program_private& from_pgm, const char* path, const char* new_name = nullptr, bool inject = false);
DLLLOCAL void importClass(ExceptionSink* xsink, qore_program_private& from_pgm, const char* path, const char* new_name = nullptr, bool inject = false, q_setpub_t set_pub = CSP_UNCHANGED);

DLLLOCAL void importHashDecl(ExceptionSink* xsink, qore_program_private& from_pgm, const char* path, const char* new_name = nullptr);
DLLLOCAL void importHashDecl(ExceptionSink* xsink, qore_program_private& from_pgm, const char* path, const char* new_name = nullptr, q_setpub_t set_pub = CSP_UNCHANGED);

DLLLOCAL const char* addString(const char* str) {
str_set_t::iterator i = str_set.lower_bound(str);
Expand Down
7 changes: 6 additions & 1 deletion include/qore/intern/typed_hash_decl_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Qore Programming Language
Copyright (C) 2003 - 2018 Qore Technologies, s.r.o.
Copyright (C) 2003 - 2019 Qore Technologies, s.r.o.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
Expand Down Expand Up @@ -126,6 +126,11 @@ friend class TypedHashDecl;
pub = true;
}

DLLLOCAL void setPrivate() {
assert(pub);
pub = false;
}

DLLLOCAL bool isSystem() const {
return sys;
}
Expand Down

0 comments on commit 550bf41

Please sign in to comment.