void termPrint(TERM *t, int isMostRight) { char showPar = getOption(OPT_SHOWPAR), greekLambda = getOption(OPT_GREEKLAMBDA), readable = getOption(OPT_READABLE); int num; switch(t->type) { case TM_VAR: case TM_ALIAS: printf("%s", t->name); break; case TM_ABSTR: //an einai church numeral typwnoyme ton antistoixo ari8mo if(readable && (num = termNumber(t)) != -1) printf("%d", num); else if(readable && termIsList(t)) termPrintList(t); else { if(showPar || !isMostRight) printf("("); printf(greekLambda ? "\xEB" : "\\"); termPrint(t->lterm, 0); printf("."); termPrint(t->rterm, 1); if(showPar || !isMostRight) printf(")"); } break; case TM_APPL: if(showPar) printf("("); termPrint(t->lterm, 0); //if(t->name) //printf(" %s ", t->name); //else printf(" "); if(!showPar && t->rterm->type == TM_APPL) printf("("); termPrint(t->rterm, isMostRight); if(!showPar && t->rterm->type == TM_APPL) printf(")"); if(showPar) printf(")"); break; } }
void ConsoleProgressImpl::updateView(vector< DownloadRecordForPrint > records, uint8_t overallDownloadPercent, size_t overallEstimatedTime, size_t speed) { // print 'em all! // sort by download numbers std::sort(records.begin(), records.end(), [](const DownloadRecordForPrint& left, const DownloadRecordForPrint& right) { return left.record.number < right.record.number; }); string viewString = format2("%d%% ", overallDownloadPercent); for (const auto& it: records) { string suffix; if (it.record.phase == DownloadRecord::Phase::Postprocessed) { suffix = " | postprocessing"; } else if (it.record.size != (size_t)-1 && it.record.size != 0 /* no sense for empty files */) { suffix = format2("/%s %.0f%%", humanReadableSizeString(it.record.size), (float)it.record.downloadedSize / it.record.size * 100); } viewString += format2("[#%zu %s %s%s]", it.record.number, it.shortAlias, humanReadableSizeString(it.record.downloadedSize), suffix); } auto speedAndTimeAppendage = string("| ") + humanReadableSpeedString(speed) + string(" | ETA: ") + humanReadableDifftimeString(overallEstimatedTime); termPrint(viewString, speedAndTimeAppendage); }
void showSubst (Term t) { #ifdef DEBUG if (!DEBUGL (5)) return; indent (); eprintf ("Substituting "); termPrint (t); eprintf (", typed "); termlistPrint (t->stype); if (realTermLeaf (t->subst)) { eprintf ("->"); termlistPrint (t->subst->stype); } else { eprintf (", composite term"); } if (t->type != VARIABLE) { eprintf (" (bound roleconstant)"); } eprintf ("\n"); #endif }
void printDeclList(char *id) { DECL *d; if(id) if(!(d = getDecl(id))) printf("Error: alias %s not found.\n", id); else { printf("%s = ", id); termPrint(d->term, 1); printf("\n"); } else for(d = declList; d; d = d->next) { printf("%s = ", d->id); termPrint(d->term, 1); printf("\n"); } }
/** * Arachne turns all role names into variables for convenience. Here we * temporarily undo it for pretty-printing. */ void roleTermPrint (const Term t) { if (t != NULL) { int typebuffer; typebuffer = t->type; t->type = GLOBAL; termPrint (t); t->type = typebuffer; } }
void termPrintList(TERM *t) { TERM *r; int i = 0; printf("["); for(r = t->rterm; r->type == TM_APPL; r = r->rterm->rterm) { if(i++ > 0) printf(", "); termPrint(r->lterm->rterm, 1); } printf("]"); }
//! Print a function void termmapPrint (Termmap f) { if (f != NULL) { eprintf ("\""); termPrint (f->term); eprintf ("\" -> %i", f->result); if (f->next != NULL) { eprintf (", "); termmapPrint (f->next); } } }
/** * Currently, inequality constraints are encoded using "NotEqual" claims. * * Here we check that their arguments have not become equal. If they are not * equal, there always exists a solution in which the values are different. The * solution generated by the algorithm that grounds the trace (for * visualisation) yields a compatible solution. * * Return true if okay - constraints can be met * Return false if not okay - at least one constraint violated * * Note that this function performs its own proof output if needed. * This allows it to pinpoint the exact constraint that is violated. * * Speed: this is certainly not the most efficient way to solve this. We are * looping over all regular events, even if there are not negative constraints * at all. Instead, we could simply collect a list of all negative constraints, * which would speed up iterating over it. */ int inequalityConstraints (const System sys) { int run; for (run = 0; run < sys->maxruns; run++) { if (sys->runs[run].protocol != INTRUDER) { int e; Roledef rd; rd = sys->runs[run].start; for (e = 0; e < sys->runs[run].step; e++) { if (rd->type == CLAIM) { // It's a claim if (isTermEqual (rd->claiminfo->type, CLAIM_Notequal)) { // TODO ASSERT: Message should be a pair for NotEqual claims if (isTermEqual (TermOp1 (rd->message), TermOp2 (rd->message))) { // Inequality violated, no solution exists that makes them inequal anymore. if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because the pattern violates an inequality constraint based on the term "); termPrint (TermOp1 (rd->message)); eprintf (".\n"); } return false; } } } rd = rd->next; } } } return true; }
//! Print a term in XML form (iteration inner) void xmlTermPrintInner (Term term) { if (term != NULL) { if (!show_substitution_path) { /* In a normal situation, variables are immediately substituted, and * only the result is output. */ term = deVar (term); } if (realTermLeaf (term)) { // Variable? if (realTermVariable (term)) { Term substbuffer; eprintf ("<var name=\""); if (term->subst == NULL) { // Free variable termPrint (term); // Must be a normal termPrint eprintf ("\" free=\"true\" />"); } else { // Bound variable substbuffer = term->subst; // Temporarily unsubst for printing term->subst = NULL; termPrint (term); // Must be a normal termPrint term->subst = substbuffer; eprintf ("\">"); xmlTermPrintInner (term->subst); eprintf ("</var>"); } } else { // Constant eprintf ("<const>"); termPrint (term); // Must be a normal termPrint eprintf ("</const>"); } } else { // Node if (realTermEncrypt (term)) { if (isTermLeaf (TermKey (term)) && inTermlist (TermKey (term)->stype, TERM_Function)) { /* function application */ eprintf ("<apply><function>"); xmlTermPrintInner (TermKey (term)); eprintf ("</function><arg>"); xmlTermPrintInner (TermOp (term)); eprintf ("</arg></apply>"); } else { eprintf ("<encrypt><op>"); xmlTermPrintInner (TermOp (term)); eprintf ("</op><key>"); xmlTermPrintInner (TermKey (term)); eprintf ("</key></encrypt>"); } } else { // Assume tuple eprintf ("<tuple><op1>"); xmlTermPrintInner (TermOp1 (term)); eprintf ("</op1><op2>"); xmlTermPrintInner (TermOp2 (term)); eprintf ("</op2></tuple>"); } } } }
/** * When something is pruned because of this function, the state space is still * considered to be complete. * *@returns true iff this state is invalid because of a theorem */ int prune_theorems (const System sys) { List bl; int run; // Check all types of the local agents according to the matching type if (!checkAllSubstitutions (sys)) { if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because some local variable was incorrectly substituted.\n"); } return true; } // Prune if agents are disallowed from performing multiple roles if (switches.oneRolePerAgent != 0) { if (multipleRolePrune (sys)) { if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because an agent may not perform multiple roles.\n"); } return true; } } // Prune if any initiator run talks to itself /** * This effectively disallows Alice from talking to Alice, for all * initiators. We still allow it for responder runs, because we assume the * responder is not checking this. */ if (switches.initUnique) { if (selfInitiators (sys) > 0) { // XXX TODO // Still need to fix proof output for this // // Pruning because some agents are equal for this role. return true; } } if (switches.respUnique) { if (selfResponders (sys) > 0) { // XXX TODO // Still need to fix proof output for this // // Pruning because some agents are equal for this role. return true; } } if (switches.roleUnique) { if (!agentsUniqueRoles (sys)) { if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because agents are not performing unique roles.\n"); } return true; } } /* The semantics imply that create event chose agent names, i.e., the range of rho is a subset of Agent. For chosen name attacks we may want to loosen that. However, this requires inserting receive events for the non-actor role variables of responders, and we don't have that yet, so technically this is a bug. Don't use. */ if (switches.chosenName) { // Check if all actors are agents for responders (initiators come next) run = 0; while (run < sys->maxruns) { if (!sys->runs[run].role->initiator) { Term actor; actor = agentOfRun (sys, run); if (!goodAgentType (actor)) { if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because the actor "); termPrint (actor); eprintf (" of run %i is not of a compatible type.\n", run); } return true; } } run++; } // Prune wrong agents type for initators if (!initiatorAgentsType (sys)) { if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned: an initiator role does not have the correct type for one of its agents.\n"); } return true; } } else { // Prune wrong agents type for runs if (!allAgentsType (sys)) { if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned: some run does not have the correct type for one of its agents.\n"); } return true; } } // Check if the actors of all other runs are not untrusted if (sys->untrusted != NULL) { int run; run = 1; while (run < sys->maxruns) { if (sys->runs[run].protocol != INTRUDER) { if (sys->runs[run].rho != NULL) { Term actor; actor = agentOfRun (sys, run); if (actor == NULL) { error ("Agent of run %i is NULL", run); } if (!isAgentTrusted (sys, actor)) { if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because the actor of run %i is untrusted.\n", run); } return true; } } else { Protocol p; globalError++; eprintf ("error: Run %i: ", run); role_name_print (run); eprintf (" has an empty agents list.\n"); eprintf ("protocol->rolenames: "); p = (Protocol) sys->runs[run].protocol; termlistPrint (p->rolenames); eprintf ("\n"); error ("Aborting."); globalError--; return true; } } run++; } } // Check for redundant patterns { if (!non_redundant ()) { if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because the pattern is redundant.\n"); } return true; } } // Check for violation of inequality constraints if (!inequalityConstraints (sys)) { // Prune, because violated return true; } /* * Check for correct orderings involving local constants * * TODO: Clarify how this works with agent name variables in a non strict-typed setting. */ if (!(switches.experimental & 8)) { if (!correctLocalOrder (sys)) { if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because this does not have the correct local order.\n"); } return true; } } /** * Check whether the bindings are valid */ bl = sys->bindings; while (bl != NULL) { Binding b; b = bl->data; // Check for "Hidden" interm goals //! @todo in the future, this can be subsumed by adding TERM_Hidden to the hidelevel constructs if (termInTerm (b->term, TERM_Hidden)) { // Prune the state: we can never meet this if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because intruder can never construct "); termPrint (b->term); eprintf ("\n"); } return true; } if (switches.experimental & 4) { // Check for SK-type function occurrences //!@todo Needs a LEMMA, although this seems to be quite straightforward to prove. // The idea is that functions are never sent as a whole, but only used in applications. //! @todo Subsumed by hidelevel lemma later if (isTermFunctionName (b->term)) { if (!inKnowledge (sys->know, b->term)) { // Not in initial knowledge of the intruder if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because the function "); termPrint (b->term); eprintf (" is not known initially to the intruder.\n"); } return true; } } } // Check for encryption levels /* * if (switches.match < 2 *! @todo Doesn't work yet as desired for Tickets. Prove lemma first. */ if (switches.experimental & 2) { if (!hasTicketSubterm (b->term)) { if (term_encryption_level (b->term) > max_encryption_level) { // Prune: we do not need to construct such terms if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because the encryption level of "); termPrint (b->term); eprintf (" is too high.\n"); } return true; } } } // To be on the safe side, we currently limit the encryption level. /** * This is valid *only* if there are no ticket-type variables. */ if (term_encryption_level (b->term) > max_encryption_level) { // Prune: we do not need to construct such terms if (sys->hasUntypedVariable) { sys->current_claim->complete = false; } if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because the encryption level of "); termPrint (b->term); eprintf (" is too high.\n"); } return true; } /** * Prune on the basis of hidelevel lemma */ if (hidelevelImpossible (sys, b->term)) { // Prune: we do not need to construct such terms if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because the hidelevel of "); termPrint (b->term); eprintf (" is impossible to satisfy.\n"); } return true; } bl = bl->next; } /* check for singular roles */ run = 0; while (run < sys->maxruns) { if (sys->runs[run].role->singular) { // This is a singular role: it therefore should not occur later on again. int run2; Term rolename; rolename = sys->runs[run].role->nameterm; run2 = run + 1; while (run2 < sys->maxruns) { Term rolename2; rolename2 = sys->runs[run2].role->nameterm; if (isTermEqual (rolename, rolename2)) { // This is not allowed: the singular role occurs twice in the semitrace. // Thus we prune. if (switches.output == PROOF) { indentPrint (); eprintf ("Pruned because the singular role "); termPrint (rolename); eprintf (" occurs more than once in the semitrace.\n"); } return true; } run2++; } } run++; } return false; }