Mantis#3187. Thank you kindly, DoranZemlja for a patch that:
Adds a warning for an LSL construct that exploits a popular list memory saving hack.GenericGridServerConcept
parent
20eb8e54ac
commit
08c76989a7
|
@ -218,6 +218,43 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
|
||||||
localID, itemID, "on_rez", new DetectParams[0],
|
localID, itemID, "on_rez", new DetectParams[0],
|
||||||
new object[] { new LSL_Types.LSLInteger(startParam) });
|
new object[] { new LSL_Types.LSLInteger(startParam) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string[] warnings = LSLCompiler.GetWarnings();
|
||||||
|
|
||||||
|
if (warnings != null && warnings.Length != 0)
|
||||||
|
{
|
||||||
|
if (presence != null && (!postOnRez))
|
||||||
|
presence.ControllingClient.SendAgentAlertMessage(
|
||||||
|
"Script saved with warnings, check debug window!",
|
||||||
|
false);
|
||||||
|
|
||||||
|
foreach (string warning in warnings)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// DISPLAY WARNING INWORLD
|
||||||
|
string text = "Warning:\n" + warning;
|
||||||
|
if (text.Length > 1100)
|
||||||
|
text = text.Substring(0, 1099);
|
||||||
|
|
||||||
|
World.SimChat(Utils.StringToBytes(text),
|
||||||
|
ChatTypeEnum.DebugChannel, 2147483647,
|
||||||
|
m_host.AbsolutePosition, m_host.Name, m_host.UUID,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
catch (Exception e2) // LEGIT: User Scripting
|
||||||
|
{
|
||||||
|
m_log.Error("[" +
|
||||||
|
m_scriptEngine.ScriptEngineName +
|
||||||
|
"]: Error displaying warning in-world: " +
|
||||||
|
e2.ToString());
|
||||||
|
m_log.Error("[" +
|
||||||
|
m_scriptEngine.ScriptEngineName + "]: " +
|
||||||
|
"Warning:\r\n" +
|
||||||
|
warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e) // LEGIT: User Scripting
|
catch (Exception e) // LEGIT: User Scripting
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
||||||
public interface ICompiler
|
public interface ICompiler
|
||||||
{
|
{
|
||||||
string PerformScriptCompile(string source, string asset);
|
string PerformScriptCompile(string source, string asset);
|
||||||
|
string[] GetWarnings();
|
||||||
Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>
|
Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>
|
||||||
LineMap();
|
LineMap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
private int m_braceCount; // for indentation
|
private int m_braceCount; // for indentation
|
||||||
private int m_CSharpLine; // the current line of generated C# code
|
private int m_CSharpLine; // the current line of generated C# code
|
||||||
private int m_CSharpCol; // the current column of generated C# code
|
private int m_CSharpCol; // the current column of generated C# code
|
||||||
|
private List<string> m_warnings = new List<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an 'empty' CSCodeGenerator instance.
|
/// Creates an 'empty' CSCodeGenerator instance.
|
||||||
|
@ -152,6 +153,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
return retstr;
|
return retstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the set of warnings generated during compilation.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string[] GetWarnings()
|
||||||
|
{
|
||||||
|
return m_warnings.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddWarning(string warning)
|
||||||
|
{
|
||||||
|
if (!m_warnings.Contains(warning))
|
||||||
|
{
|
||||||
|
m_warnings.Add(warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recursively called to generate each type of node. Will generate this
|
/// Recursively called to generate each type of node. Will generate this
|
||||||
/// node, then all it's children.
|
/// node, then all it's children.
|
||||||
|
@ -446,6 +464,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
{
|
{
|
||||||
string retstr = String.Empty;
|
string retstr = String.Empty;
|
||||||
|
|
||||||
|
List<string> identifiers = new List<string>();
|
||||||
|
checkForMultipleAssignments(identifiers, a);
|
||||||
|
|
||||||
retstr += GenerateNode((SYMBOL) a.kids.Pop());
|
retstr += GenerateNode((SYMBOL) a.kids.Pop());
|
||||||
retstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
|
retstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
|
||||||
foreach (SYMBOL kid in a.kids)
|
foreach (SYMBOL kid in a.kids)
|
||||||
|
@ -454,6 +475,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
return retstr;
|
return retstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This code checks for LSL of the following forms, and generates a
|
||||||
|
// warning if it finds them.
|
||||||
|
//
|
||||||
|
// list l = [ "foo" ];
|
||||||
|
// l = (l=[]) + l + ["bar"];
|
||||||
|
// (produces l=["foo","bar"] in SL but l=["bar"] in OS)
|
||||||
|
//
|
||||||
|
// integer i;
|
||||||
|
// integer j;
|
||||||
|
// i = (j = 3) + (j = 4) + (j = 5);
|
||||||
|
// (produces j=3 in SL but j=5 in OS)
|
||||||
|
//
|
||||||
|
// Without this check, that code passes compilation, but does not do what
|
||||||
|
// the end user expects, because LSL in SL evaluates right to left instead
|
||||||
|
// of left to right.
|
||||||
|
//
|
||||||
|
// The theory here is that producing an error and alerting the end user that
|
||||||
|
// something needs to change is better than silently generating incorrect code.
|
||||||
|
private void checkForMultipleAssignments(List<string> identifiers, SYMBOL s)
|
||||||
|
{
|
||||||
|
if (s is Assignment)
|
||||||
|
{
|
||||||
|
Assignment a = (Assignment)s;
|
||||||
|
string newident = null;
|
||||||
|
|
||||||
|
if (a.kids[0] is Declaration)
|
||||||
|
{
|
||||||
|
newident = ((Declaration)a.kids[0]).Id;
|
||||||
|
}
|
||||||
|
else if (a.kids[0] is IDENT)
|
||||||
|
{
|
||||||
|
newident = ((IDENT)a.kids[0]).yytext;
|
||||||
|
}
|
||||||
|
else if (a.kids[0] is IdentDotExpression)
|
||||||
|
{
|
||||||
|
newident = ((IdentDotExpression)a.kids[0]).Name; // +"." + ((IdentDotExpression)a.kids[0]).Member;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddWarning(String.Format("Multiple assignments checker internal error '{0}' at line {1} column {2}.", a.kids[0].GetType(), ((SYMBOL)a.kids[0]).Line - 1, ((SYMBOL)a.kids[0]).Position));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identifiers.Contains(newident))
|
||||||
|
{
|
||||||
|
AddWarning(String.Format("Multiple assignments to '{0}' at line {1} column {2}; results may differ between LSL and OSSL.", newident, ((SYMBOL)a.kids[0]).Line - 1, ((SYMBOL)a.kids[0]).Position));
|
||||||
|
}
|
||||||
|
identifiers.Add(newident);
|
||||||
|
}
|
||||||
|
|
||||||
|
int index;
|
||||||
|
for (index = 0; index < s.kids.Count; index++)
|
||||||
|
{
|
||||||
|
checkForMultipleAssignments(identifiers, (SYMBOL) s.kids[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates the code for a ReturnStatement node.
|
/// Generates the code for a ReturnStatement node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -76,6 +76,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap;
|
private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap;
|
||||||
private ICodeConverter LSL_Converter;
|
private ICodeConverter LSL_Converter;
|
||||||
|
|
||||||
|
private List<string> m_warnings = new List<string>();
|
||||||
|
|
||||||
// private object m_syncy = new object();
|
// private object m_syncy = new object();
|
||||||
|
|
||||||
private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
|
private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
|
||||||
|
@ -336,6 +338,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
LSL_Converter = (ICodeConverter)new CSCodeGenerator();
|
LSL_Converter = (ICodeConverter)new CSCodeGenerator();
|
||||||
compileScript = LSL_Converter.Convert(Script);
|
compileScript = LSL_Converter.Convert(Script);
|
||||||
|
|
||||||
|
// copy converter warnings into our warnings.
|
||||||
|
foreach(string warning in LSL_Converter.GetWarnings())
|
||||||
|
{
|
||||||
|
AddWarning(warning);
|
||||||
|
}
|
||||||
|
|
||||||
m_positionMap = ((CSCodeGenerator) LSL_Converter).PositionMap;
|
m_positionMap = ((CSCodeGenerator) LSL_Converter).PositionMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,6 +381,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
return CompileFromDotNetText(compileScript, l, asset);
|
return CompileFromDotNetText(compileScript, l, asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string[] GetWarnings()
|
||||||
|
{
|
||||||
|
return m_warnings.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddWarning(string warning)
|
||||||
|
{
|
||||||
|
if (!m_warnings.Contains(warning))
|
||||||
|
{
|
||||||
|
m_warnings.Add(warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static string CreateJSCompilerScript(string compileScript)
|
private static string CreateJSCompilerScript(string compileScript)
|
||||||
{
|
{
|
||||||
compileScript = String.Empty +
|
compileScript = String.Empty +
|
||||||
|
|
|
@ -33,5 +33,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
public interface ICodeConverter
|
public interface ICodeConverter
|
||||||
{
|
{
|
||||||
string Convert(string script);
|
string Convert(string script);
|
||||||
|
string[] GetWarnings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -516,6 +516,38 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
m_AddingAssemblies[assembly]++;
|
m_AddingAssemblies[assembly]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string[] warnings = m_Compiler.GetWarnings();
|
||||||
|
|
||||||
|
if (warnings != null && warnings.Length != 0)
|
||||||
|
{
|
||||||
|
if (presence != null && (!postOnRez))
|
||||||
|
presence.ControllingClient.SendAgentAlertMessage("Script saved with warnings, check debug window!", false);
|
||||||
|
|
||||||
|
foreach (string warning in warnings)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// DISPLAY WARNING INWORLD
|
||||||
|
string text = "Warning:\n" + warning;
|
||||||
|
if (text.Length > 1000)
|
||||||
|
text = text.Substring(0, 1000);
|
||||||
|
World.SimChat(Utils.StringToBytes(text),
|
||||||
|
ChatTypeEnum.DebugChannel, 2147483647,
|
||||||
|
part.AbsolutePosition,
|
||||||
|
part.Name, part.UUID, false);
|
||||||
|
}
|
||||||
|
catch (Exception e2) // LEGIT: User Scripting
|
||||||
|
{
|
||||||
|
m_log.Error("[XEngine]: " +
|
||||||
|
"Error displaying warning in-world: " +
|
||||||
|
e2.ToString());
|
||||||
|
m_log.Error("[XEngine]: " +
|
||||||
|
"Warning:\r\n" +
|
||||||
|
warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue